Home | History | Annotate | Download | only in wtf
      1 /*
      2  * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #ifndef WTF_PassOwnPtr_h
     27 #define WTF_PassOwnPtr_h
     28 
     29 #include "Assertions.h"
     30 #include "NullPtr.h"
     31 #include "OwnPtrCommon.h"
     32 #include "TypeTraits.h"
     33 
     34 // Remove this once we make all WebKit code compatible with stricter rules about PassOwnPtr.
     35 #define LOOSE_PASS_OWN_PTR
     36 
     37 namespace WTF {
     38 
     39     // Unlike most of our smart pointers, PassOwnPtr can take either the pointer type or the pointed-to type.
     40 
     41     template<typename T> class OwnPtr;
     42     template<typename T> class PassOwnPtr;
     43     template<typename T> PassOwnPtr<T> adoptPtr(T*);
     44 
     45     template<typename T> class PassOwnPtr {
     46     public:
     47         typedef typename RemovePointer<T>::Type ValueType;
     48         typedef ValueType* PtrType;
     49 
     50         PassOwnPtr() : m_ptr(0) { }
     51 
     52         // It somewhat breaks the type system to allow transfer of ownership out of
     53         // a const PassOwnPtr. However, it makes it much easier to work with PassOwnPtr
     54         // temporaries, and we don't have a need to use real const PassOwnPtrs anyway.
     55         PassOwnPtr(const PassOwnPtr& o) : m_ptr(o.leakPtr()) { }
     56         template<typename U> PassOwnPtr(const PassOwnPtr<U>& o) : m_ptr(o.leakPtr()) { }
     57 
     58         ~PassOwnPtr() { deleteOwnedPtr(m_ptr); }
     59 
     60         PtrType get() const { return m_ptr; }
     61 
     62         void clear();
     63         PtrType leakPtr() const WARN_UNUSED_RETURN;
     64 
     65         ValueType& operator*() const { ASSERT(m_ptr); return *m_ptr; }
     66         PtrType operator->() const { ASSERT(m_ptr); return m_ptr; }
     67 
     68         bool operator!() const { return !m_ptr; }
     69 
     70         // This conversion operator allows implicit conversion to bool but not to other integer types.
     71         typedef PtrType PassOwnPtr::*UnspecifiedBoolType;
     72         operator UnspecifiedBoolType() const { return m_ptr ? &PassOwnPtr::m_ptr : 0; }
     73 
     74         PassOwnPtr& operator=(const PassOwnPtr<T>&);
     75 #if !defined(LOOSE_PASS_OWN_PTR) || !HAVE(NULLPTR)
     76         PassOwnPtr& operator=(std::nullptr_t) { clear(); return *this; }
     77 #endif
     78         template<typename U> PassOwnPtr& operator=(const PassOwnPtr<U>&);
     79 
     80         template<typename U> friend PassOwnPtr<U> adoptPtr(U*);
     81 
     82 #ifdef LOOSE_PASS_OWN_PTR
     83         PassOwnPtr(PtrType ptr) : m_ptr(ptr) { }
     84         PassOwnPtr& operator=(PtrType);
     85 #endif
     86 
     87     private:
     88 #ifndef LOOSE_PASS_OWN_PTR
     89         explicit PassOwnPtr(PtrType ptr) : m_ptr(ptr) { }
     90 #endif
     91 
     92         mutable PtrType m_ptr;
     93     };
     94 
     95     template<typename T> inline void PassOwnPtr<T>::clear()
     96     {
     97         PtrType ptr = m_ptr;
     98         m_ptr = 0;
     99         deleteOwnedPtr(ptr);
    100     }
    101 
    102     template<typename T> inline typename PassOwnPtr<T>::PtrType PassOwnPtr<T>::leakPtr() const
    103     {
    104         PtrType ptr = m_ptr;
    105         m_ptr = 0;
    106         return ptr;
    107     }
    108 
    109 #ifdef LOOSE_PASS_OWN_PTR
    110     template<typename T> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(PtrType optr)
    111     {
    112         PtrType ptr = m_ptr;
    113         m_ptr = optr;
    114         ASSERT(!ptr || m_ptr != ptr);
    115         if (ptr)
    116             deleteOwnedPtr(ptr);
    117         return *this;
    118     }
    119 #endif
    120 
    121     template<typename T> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(const PassOwnPtr<T>& optr)
    122     {
    123         PtrType ptr = m_ptr;
    124         m_ptr = optr.leakPtr();
    125         ASSERT(!ptr || m_ptr != ptr);
    126         if (ptr)
    127             deleteOwnedPtr(ptr);
    128         return *this;
    129     }
    130 
    131     template<typename T> template<typename U> inline PassOwnPtr<T>& PassOwnPtr<T>::operator=(const PassOwnPtr<U>& optr)
    132     {
    133         PtrType ptr = m_ptr;
    134         m_ptr = optr.leakPtr();
    135         ASSERT(!ptr || m_ptr != ptr);
    136         if (ptr)
    137             deleteOwnedPtr(ptr);
    138         return *this;
    139     }
    140 
    141     template<typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, const PassOwnPtr<U>& b)
    142     {
    143         return a.get() == b.get();
    144     }
    145 
    146     template<typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, const OwnPtr<U>& b)
    147     {
    148         return a.get() == b.get();
    149     }
    150 
    151     template<typename T, typename U> inline bool operator==(const OwnPtr<T>& a, const PassOwnPtr<U>& b)
    152     {
    153         return a.get() == b.get();
    154     }
    155 
    156     template<typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, U* b)
    157     {
    158         return a.get() == b;
    159     }
    160 
    161     template<typename T, typename U> inline bool operator==(T* a, const PassOwnPtr<U>& b)
    162     {
    163         return a == b.get();
    164     }
    165 
    166     template<typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, const PassOwnPtr<U>& b)
    167     {
    168         return a.get() != b.get();
    169     }
    170 
    171     template<typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, const OwnPtr<U>& b)
    172     {
    173         return a.get() != b.get();
    174     }
    175 
    176     template<typename T, typename U> inline bool operator!=(const OwnPtr<T>& a, const PassOwnPtr<U>& b)
    177     {
    178         return a.get() != b.get();
    179     }
    180 
    181     template<typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, U* b)
    182     {
    183         return a.get() != b;
    184     }
    185 
    186     template<typename T, typename U> inline bool operator!=(T* a, const PassOwnPtr<U>& b)
    187     {
    188         return a != b.get();
    189     }
    190 
    191     template<typename T> inline PassOwnPtr<T> adoptPtr(T* ptr)
    192     {
    193         return PassOwnPtr<T>(ptr);
    194     }
    195 
    196     template<typename T, typename U> inline PassOwnPtr<T> static_pointer_cast(const PassOwnPtr<U>& p)
    197     {
    198         return adoptPtr(static_cast<T*>(p.leakPtr()));
    199     }
    200 
    201     template<typename T, typename U> inline PassOwnPtr<T> const_pointer_cast(const PassOwnPtr<U>& p)
    202     {
    203         return adoptPtr(const_cast<T*>(p.leakPtr()));
    204     }
    205 
    206     template<typename T> inline T* getPtr(const PassOwnPtr<T>& p)
    207     {
    208         return p.get();
    209     }
    210 
    211 } // namespace WTF
    212 
    213 using WTF::PassOwnPtr;
    214 using WTF::adoptPtr;
    215 using WTF::const_pointer_cast;
    216 using WTF::static_pointer_cast;
    217 
    218 #endif // WTF_PassOwnPtr_h
    219