WebKit Smart pointer-Refptr, PASSREFPTR

Source: Internet
Author: User

History

Before 2005, many objects in WebKit were quoted as reference counts. They implement this pattern by inheriting the refcounted "class template. Refcounted mainly implements the two functions of ref () and Deref (). Call ref () to increase the reference count when you need to reference the object, and call the Deref () function to reduce the reference count when you no longer need the object. Ref () and deref () need to appear in pairs. This is like using New/delete, where multiple calls, fewer calls, and no calls always occur. If the compiler can automatically complete the ref, Deref calls, C + + programming bugs can be reduced by at least half.

PS: While most of the problems with the C + + programming are ultimately memory problems, the root cause may be logical and process problems. In other words, if the compiler can manage memory automatically, it can really reduce the burden on the programmer greatly.

Refcounted several of the main functions are implemented as follows:

void ref () {++m_refcount;} Returns whether the pointer should be freed or Not.bool derefbase () {Unsigned temprefcount = m_refcount-1;if (!tempref Count) {return true;} M_refcount = Temprefcount;return false;} void Deref () {if (Derefbase ()) Delete static_cast<t*> (this);}

refptr

Refptr can be applied to any object with a ref () and deref () member function, which implements intelligent management of pointers by automatically invoking the object's ref () and Deref (). Many objects in WebKit implement reference-count patterns (with ref () and Deref () functions) by inheriting refcounted.

Refptr automatically calls ref () when the value is passed in to increase the reference count, and automatically calls Deref () on outgoing values to reduce the reference count. We know that when you call Deref (), if the reference count is 1, the corresponding object is deleted.

Refptr is used to manage pointers, which means you have to have pointers first, how the pointers come, the change is not in them, but also new out. New came out of our called bare hands, the so-called refptr management is to the new out of the bare pointer to a Refptr object. Inside the smart pointer, delete the bare pointers you gave it to manage at the right time.

Assign a bare pointer to a refptr by Adoptref (). At any time, the new object should call Adoptref immediately, so there is no problem of forgetting to call Deref ().

refptr<foo> foo = adoptref (new foo ());

In efficiency, Foo assigns the reference count to 1 when it is created, so it is not possible to assign a new object directly to Refptr, because doing so will cause the object of new to never be freed. So you need to use ADOPTREF to transfer ownership.

Refcountedbase (): M_refcount (1) {}

Adoptref implementation (PASSREFPTR.H):

Template<typename t> inline passrefptr<t> adoptref (t* p) {    adopted (p);    Return passrefptr<t> (P, passrefptr<t>::adopt);}

One of the adopted actually does nothing, as defined below (PassRef.h):

inline void adopted (const void*) {}

The next call to Passrefptr is defined as follows:

Enum Adopttag {adopt}; Passrefptr (t* ptr, Adopttag): M_ptr (PTR) {}

The function creates a passrefptr temporary object with a bare pointer for the parameter. In the above example, the actual assignment is to a Refptr object, using the following type conversion function:

Template<typename t> template<typename u> inline refptr<t>::refptr (const passrefptr<u>& o )        : M_ptr (O.leakref ()) {}
Template<typename t> inline t* passrefptr<t>::leakref () const{    t* ptr = m_ptr;    M_ptr = nullptr;    return ptr;}

Leakref () transfers a passrefptr to a bare pointer.

In short, adoptref is to put an inherited from the Refcounted object to refptr management.


Disadvantages of Refptr

Let's look at the following example

example, not preferred style; Should use Refcountedand adoptref (see below) refptr<node> Createspecialnode () {      refptr<node> a = new Node ;       A->setspecial (true);        return A;} Refptr<node> B = Createspecialnode ();

For ease of discussion, we assume that a node object starts with a reference count of 0. When it is assigned to a, the reference count is increased to 1. The reference count is incremented to 2 when the return value is created, and then when a is destroyed, the reference count is reduced to 1. When B is created, the reference count is incremented to 2, then the return value of Createspecialnode is destroyed, and the reference count is reduced to 1.

If the compiler implements the return value optimization, the number of reference count increases and decreases may be reduced.

If both the parameter and the return value are smart pointers, the overhead associated with the reference count is even greater. The way to solve this problem is to use passrefptr.

Passptrref

Passrefptr is a little different from refptr, when you copy a passrefptr or assign a passrefptr value to a refptr or another passrefptr, the original pointer value is set to 0; The operation does not change the value of the reference count.

Let's look at the implementation of PASSPTRREF with respect to the value of the pass:

Passrefptr (const passrefptr& O): M_ptr (O.leakref ()) {}template<typename u> passrefptr (ConstPassRefPtr<U >& o): M_ptr (O.leakref ()) {}template<typename t> inline t*passrefptr<t>::leakref () const{    T* ptr = m_ptr;    M_ptr =nullptr;    return ptr;}

Leakref is the transfer of the management pointer to the recipient of the value, and does not involve reference counting operations. One thing to keep in mind is that a Passrefptr object that is a right value is no longer available. Therefore, be sure to use passrefptr only in function parameters and return types.

PASSREFPTR exists to reduce the reference count operations that result from using refptr when parameter passing and function return.

Passrefptr and Refptr

After initializing the refptr with a passrefptr, or assigning to Refptr, the original passrefptr can no longer be used

Template<typename t> template<typename u>inline refptr<t>::refptr (const PassRefPtr<U>& o )        : M_ptr (O.leakref ()) {}

When initializing passrefptr with a refptr, reference counting operations are not involved.

Template<typename t> template<typename u> inlinepassrefptr<t>::P assrefptr (const RefPtr<U> & O)        : m_ptr (O.get ()) {    t* ptr = m_ptr;   Refifnotnull (PTR);}

Therefore, make sure that you do not release refptr-managed pointers before Passrefptr is used. The following principles of use do not apply:

Use passrefptr only in function arguments and return types, and copy function arguments to a refptr.

bare hands with refptr, Passrefptr

They can be converted to each other, but in fact it is not necessary, you can use the same as the bare pointer refptr, PASSREFPTR, because overloaded with the operator "*", "-"

t& operator* () const {return *m_ptr;} Always_inline t* operator-> () const {return m_ptr;}

Using the Guide local variables

If you can determine ownership and life cycle, a local variable can be a bare pointer.

If you are unsure and you need to guarantee ownership or declaration cycles, you should use Refptr.

Local variables should never be a passrefptr


Data members

If you can determine ownership and life cycle, a data member can be a bare pointer.

If you are unsure and you need to guarantee ownership or declaration cycles, you should use Refptr.

Data members should never be a passrefptr


function parameters

If a function does not occupy an object, it should use a bare pointer as a parameter.

If a function needs to occupy an object, you should use Passrefptr. Most of the setter functions are like this. Parameters should be passed to a refptr at the beginning of the function, unless the use of parameters is very simple. A "PRP" prefix can be used to name the parameter.


function return value

If the function returns an object, but does not transfer its ownership, the return value should be a bare pointer. For example, most getter functions.

If the function return value is a new object or if ownership needs to be transferred, the return value should use Passrefptr. The local variable is usually a refptr, so release is often called in the return statement to transfer a refptr to a passrefptr.

Passrefptr<t> release () {passrefptr<t> tmp =adoptref (m_ptr); m_ptr = nullptr; return tmp;}

New Object

At any time, the new object should be placed in refptr immediately to allow the smart pointer to automatically complete all reference counting operations.

For refcounted objects, you should do this through the ADOPTREF function.

For non-refcounted objects, the best practice is to use a private constructor and a public create function that returns a passrefptr.

Class Item {public:    Passrefptr<item>createitem () {}private:    Item () {}}; Passrefptr<item> CreateItem () {    refptr<item>a = new Item;    

Reference: http://blog.csdn.net/wy5761/article/details/20654275



WebKit Smart pointer-Refptr, PASSREFPTR

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.