Home | History | Annotate | Download | only in platform
      1 /*
      2  * Copyright (C) 2010 Google 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 are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #ifndef WebPrivatePtr_h
     32 #define WebPrivatePtr_h
     33 
     34 #include "WebCommon.h"
     35 
     36 #if INSIDE_BLINK
     37 #include "platform/heap/Handle.h"
     38 #include "wtf/PassRefPtr.h"
     39 #include "wtf/TypeTraits.h"
     40 #endif
     41 
     42 namespace blink {
     43 
     44 #if INSIDE_BLINK
     45 enum LifetimeManagementType {
     46     RefCountedLifetime,
     47     GarbageCollectedLifetime,
     48     RefCountedGarbageCollectedLifetime
     49 };
     50 
     51 template<typename T>
     52 class LifetimeOf {
     53     static const bool isGarbageCollected = WTF::IsSubclassOfTemplate<T, GarbageCollected>::value;
     54     static const bool isRefCountedGarbageCollected = WTF::IsSubclassOfTemplate<T, RefCountedGarbageCollected>::value;
     55 public:
     56     static const LifetimeManagementType value =
     57         !isGarbageCollected ? RefCountedLifetime :
     58         isRefCountedGarbageCollected ? RefCountedGarbageCollectedLifetime : GarbageCollectedLifetime;
     59 };
     60 
     61 template<typename T, LifetimeManagementType lifetime>
     62 class PtrStorageImpl;
     63 
     64 template<typename T>
     65 class PtrStorageImpl<T, RefCountedLifetime> {
     66 public:
     67     typedef PassRefPtr<T> BlinkPtrType;
     68 
     69     void assign(const BlinkPtrType& val)
     70     {
     71         release();
     72         m_ptr = val.leakRef();
     73     }
     74 
     75     void assign(const PtrStorageImpl& other)
     76     {
     77         release();
     78         T* val = other.get();
     79         WTF::refIfNotNull(val);
     80         m_ptr = val;
     81     }
     82 
     83     T* get() const { return m_ptr; }
     84 
     85     void release()
     86     {
     87         WTF::derefIfNotNull(m_ptr);
     88         m_ptr = 0;
     89     }
     90 
     91 private:
     92     T* m_ptr;
     93 };
     94 
     95 template<typename T>
     96 class PtrStorageImpl<T, GarbageCollectedLifetime> {
     97 public:
     98     void assign(const RawPtr<T>& val)
     99     {
    100         if (!val) {
    101             release();
    102             return;
    103         }
    104 
    105         if (!m_handle)
    106             m_handle = new Persistent<T>();
    107 
    108         (*m_handle) = val;
    109     }
    110 
    111     void assign(T* ptr) { assign(RawPtr<T>(ptr)); }
    112     template<typename U> void assign(const RawPtr<U>& val) { assign(RawPtr<T>(val)); }
    113 
    114     void assign(const PtrStorageImpl& other) { assign(other.get()); }
    115 
    116     T* get() const { return m_handle ? m_handle->get() : 0; }
    117 
    118     void release()
    119     {
    120         delete m_handle;
    121         m_handle = 0;
    122     }
    123 
    124 private:
    125     Persistent<T>* m_handle;
    126 };
    127 
    128 template<typename T>
    129 class PtrStorageImpl<T, RefCountedGarbageCollectedLifetime> : public PtrStorageImpl<T, GarbageCollectedLifetime> {
    130 public:
    131     void assign(const PassRefPtrWillBeRawPtr<T>& val) { PtrStorageImpl<T, GarbageCollectedLifetime>::assign(val.get()); }
    132 
    133     void assign(const PtrStorageImpl& other) { PtrStorageImpl<T, GarbageCollectedLifetime>::assign(other.get()); }
    134 };
    135 
    136 template<typename T>
    137 class PtrStorage : public PtrStorageImpl<T, LifetimeOf<T>::value> {
    138 public:
    139     static PtrStorage& fromSlot(void** slot)
    140     {
    141         COMPILE_ASSERT(sizeof(PtrStorage) == sizeof(void*), PtrStorage_must_be_pointer_size);
    142         return *reinterpret_cast<PtrStorage*>(slot);
    143     }
    144 
    145     static const PtrStorage& fromSlot(void* const* slot)
    146     {
    147         COMPILE_ASSERT(sizeof(PtrStorage) == sizeof(void*), PtrStorage_must_be_pointer_size);
    148         return *reinterpret_cast<const PtrStorage*>(slot);
    149     }
    150 
    151 private:
    152     // Prevent construction via normal means.
    153     PtrStorage();
    154     PtrStorage(const PtrStorage&);
    155 };
    156 #endif
    157 
    158 
    159 // This class is an implementation detail of the Blink API. It exists to help
    160 // simplify the implementation of Blink interfaces that merely wrap a reference
    161 // counted WebCore class.
    162 //
    163 // A typical implementation of a class which uses WebPrivatePtr might look like
    164 // this:
    165 //    class WebFoo {
    166 //    public:
    167 //        BLINK_EXPORT ~WebFoo();
    168 //        WebFoo() { }
    169 //        WebFoo(const WebFoo& other) { assign(other); }
    170 //        WebFoo& operator=(const WebFoo& other)
    171 //        {
    172 //            assign(other);
    173 //            return *this;
    174 //        }
    175 //        BLINK_EXPORT void assign(const WebFoo&);  // Implemented in the body.
    176 //
    177 //        // Methods that are exposed to Chromium and which are specific to
    178 //        // WebFoo go here.
    179 //        BLINK_EXPORT doWebFooThing();
    180 //
    181 //        // Methods that are used only by other Blink classes should only be
    182 //        // declared when INSIDE_BLINK is set.
    183 //    #if INSIDE_BLINK
    184 //        WebFoo(const WTF::PassRefPtr<Foo>&);
    185 //    #endif
    186 //
    187 //    private:
    188 //        WebPrivatePtr<Foo> m_private;
    189 //    };
    190 //
    191 //    // WebFoo.cpp
    192 //    WebFoo::~WebFoo() { m_private.reset(); }
    193 //    void WebFoo::assign(const WebFoo& other) { ... }
    194 //
    195 template <typename T>
    196 class WebPrivatePtr {
    197 public:
    198     WebPrivatePtr() : m_storage(0) { }
    199     ~WebPrivatePtr()
    200     {
    201         // We don't destruct the object pointed by m_ptr here because we don't
    202         // want to expose destructors of core classes to embedders. We should
    203         // call reset() manually in destructors of classes with WebPrivatePtr
    204         // members.
    205         BLINK_ASSERT(!m_storage);
    206     }
    207 
    208     bool isNull() const { return !m_storage; }
    209 
    210 #if INSIDE_BLINK
    211     template<typename U>
    212     WebPrivatePtr(const U& ptr)
    213         : m_storage(0)
    214     {
    215         storage().assign(ptr);
    216     }
    217 
    218     void reset() { storage().release(); }
    219 
    220     WebPrivatePtr<T>& operator=(const WebPrivatePtr<T>& other)
    221     {
    222         storage().assign(other.storage());
    223         return *this;
    224     }
    225 
    226     template<typename U>
    227     WebPrivatePtr<T>& operator=(const U& ptr)
    228     {
    229         storage().assign(ptr);
    230         return *this;
    231     }
    232 
    233     T* get() const { return storage().get(); }
    234 
    235     T& operator*() const
    236     {
    237         ASSERT(m_storage);
    238         return *get();
    239     }
    240 
    241     T* operator->() const
    242     {
    243         ASSERT(m_storage);
    244         return get();
    245     }
    246 #endif
    247 
    248 private:
    249 #if INSIDE_BLINK
    250     PtrStorage<T>& storage() { return PtrStorage<T>::fromSlot(&m_storage); }
    251     const PtrStorage<T>& storage() const { return PtrStorage<T>::fromSlot(&m_storage); }
    252 #endif
    253 
    254 #if !INSIDE_BLINK
    255     // Disable the assignment operator; we define it above for when
    256     // INSIDE_BLINK is set, but we need to make sure that it is not
    257     // used outside there; the compiler-provided version won't handle reference
    258     // counting properly.
    259     WebPrivatePtr<T>& operator=(const WebPrivatePtr<T>& other);
    260 #endif
    261     // Disable the copy constructor; classes that contain a WebPrivatePtr
    262     // should implement their copy constructor using assign().
    263     WebPrivatePtr(const WebPrivatePtr<T>&);
    264 
    265     void* m_storage;
    266 };
    267 
    268 } // namespace blink
    269 
    270 #endif
    271