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 
     38 namespace WebCore { template<typename T> class TreeShared; }
     39 
     40 #include "platform/heap/Handle.h"
     41 #include "wtf/PassRefPtr.h"
     42 #include "wtf/TypeTraits.h"
     43 #endif
     44 
     45 namespace blink {
     46 
     47 #if INSIDE_BLINK
     48 enum LifetimeManagementType {
     49     RefCountedLifetime,
     50     GarbageCollectedLifetime,
     51     RefCountedGarbageCollectedLifetime
     52 };
     53 
     54 template<typename T>
     55 class LifetimeOf {
     56     static const bool isGarbageCollected = WTF::IsSubclassOfTemplate<T, WebCore::GarbageCollected>::value;
     57     static const bool isRefCountedGarbageCollected = WTF::IsSubclassOfTemplate<T, WebCore::RefCountedGarbageCollected>::value;
     58 public:
     59     static const LifetimeManagementType value =
     60         !isGarbageCollected ? RefCountedLifetime :
     61         isRefCountedGarbageCollected ? RefCountedGarbageCollectedLifetime : GarbageCollectedLifetime;
     62 };
     63 
     64 template<typename T, LifetimeManagementType lifetime>
     65 class PtrStorageImpl;
     66 
     67 template<typename T>
     68 class PtrStorageImpl<T, RefCountedLifetime> {
     69 public:
     70     typedef PassRefPtr<T> BlinkPtrType;
     71 
     72     void assign(const BlinkPtrType& val)
     73     {
     74         release();
     75         m_ptr = val.leakRef();
     76     }
     77 
     78     void assign(const PtrStorageImpl& other)
     79     {
     80         release();
     81         T* val = other.get();
     82         if (val)
     83             val->ref();
     84         m_ptr = val;
     85     }
     86 
     87     T* get() const { return m_ptr; }
     88 
     89     void release()
     90     {
     91         if (m_ptr)
     92             m_ptr->deref();
     93         m_ptr = 0;
     94     }
     95 
     96 private:
     97     T* m_ptr;
     98 };
     99 
    100 template<typename T>
    101 class PtrStorageImpl<T, GarbageCollectedLifetime> {
    102 public:
    103     void assign(const RawPtr<T>& val)
    104     {
    105         if (!val) {
    106             release();
    107             return;
    108         }
    109 
    110         if (!m_handle)
    111             m_handle = new WebCore::Persistent<T>();
    112 
    113         (*m_handle) = val;
    114     }
    115 
    116     void assign(T* ptr) { assign(RawPtr<T>(ptr)); }
    117     template<typename U> void assign(const RawPtr<U>& val) { assign(RawPtr<T>(val)); }
    118 
    119     void assign(const PtrStorageImpl& other) { assign(other.get()); }
    120 
    121     T* get() const { return m_handle ? m_handle->get() : 0; }
    122 
    123     void release()
    124     {
    125         delete m_handle;
    126         m_handle = 0;
    127     }
    128 
    129 private:
    130     WebCore::Persistent<T>* m_handle;
    131 };
    132 
    133 template<typename T>
    134 class PtrStorageImpl<T, RefCountedGarbageCollectedLifetime> : public PtrStorageImpl<T, GarbageCollectedLifetime> {
    135 public:
    136     void assign(const PassRefPtrWillBeRawPtr<T>& val) { PtrStorageImpl<T, GarbageCollectedLifetime>::assign(val.get()); }
    137 
    138     void assign(const PtrStorageImpl& other) { PtrStorageImpl<T, GarbageCollectedLifetime>::assign(other.get()); }
    139 };
    140 
    141 template<typename T>
    142 class PtrStorage : public PtrStorageImpl<T, LifetimeOf<T>::value> {
    143 public:
    144     static PtrStorage& fromSlot(void** slot)
    145     {
    146         COMPILE_ASSERT(sizeof(PtrStorage) == sizeof(void*), PtrStorage_must_be_pointer_size);
    147         return *reinterpret_cast<PtrStorage*>(slot);
    148     }
    149 
    150     static const PtrStorage& fromSlot(void* const* slot)
    151     {
    152         COMPILE_ASSERT(sizeof(PtrStorage) == sizeof(void*), PtrStorage_must_be_pointer_size);
    153         return *reinterpret_cast<const PtrStorage*>(slot);
    154     }
    155 
    156 private:
    157     // Prevent construction via normal means.
    158     PtrStorage();
    159     PtrStorage(const PtrStorage&);
    160 };
    161 #endif
    162 
    163 
    164 // This class is an implementation detail of the Blink API. It exists to help
    165 // simplify the implementation of Blink interfaces that merely wrap a reference
    166 // counted WebCore class.
    167 //
    168 // A typical implementation of a class which uses WebPrivatePtr might look like
    169 // this:
    170 //    class WebFoo {
    171 //    public:
    172 //        BLINK_EXPORT ~WebFoo();
    173 //        WebFoo() { }
    174 //        WebFoo(const WebFoo& other) { assign(other); }
    175 //        WebFoo& operator=(const WebFoo& other)
    176 //        {
    177 //            assign(other);
    178 //            return *this;
    179 //        }
    180 //        BLINK_EXPORT void assign(const WebFoo&);  // Implemented in the body.
    181 //
    182 //        // Methods that are exposed to Chromium and which are specific to
    183 //        // WebFoo go here.
    184 //        BLINK_EXPORT doWebFooThing();
    185 //
    186 //        // Methods that are used only by other Blink classes should only be
    187 //        // declared when INSIDE_BLINK is set.
    188 //    #if INSIDE_BLINK
    189 //        WebFoo(const WTF::PassRefPtr<WebCore::Foo>&);
    190 //    #endif
    191 //
    192 //    private:
    193 //        WebPrivatePtr<WebCore::Foo> m_private;
    194 //    };
    195 //
    196 //    // WebFoo.cpp
    197 //    WebFoo::~WebFoo() { m_private.reset(); }
    198 //    void WebFoo::assign(const WebFoo& other) { ... }
    199 //
    200 template <typename T>
    201 class WebPrivatePtr {
    202 public:
    203     WebPrivatePtr() : m_storage(0) { }
    204     ~WebPrivatePtr()
    205     {
    206         // We don't destruct the object pointed by m_ptr here because we don't
    207         // want to expose destructors of core classes to embedders. We should
    208         // call reset() manually in destructors of classes with WebPrivatePtr
    209         // members.
    210         BLINK_ASSERT(!m_storage);
    211     }
    212 
    213     bool isNull() const { return !m_storage; }
    214 
    215 #if INSIDE_BLINK
    216     template<typename U>
    217     WebPrivatePtr(const U& ptr)
    218         : m_storage(0)
    219     {
    220         storage().assign(ptr);
    221     }
    222 
    223     void reset() { storage().release(); }
    224 
    225     WebPrivatePtr<T>& operator=(const WebPrivatePtr<T>& other)
    226     {
    227         storage().assign(other.storage());
    228         return *this;
    229     }
    230 
    231     template<typename U>
    232     WebPrivatePtr<T>& operator=(const U& ptr)
    233     {
    234         storage().assign(ptr);
    235         return *this;
    236     }
    237 
    238     T* get() const { return storage().get(); }
    239 
    240     T& operator*() const
    241     {
    242         ASSERT(m_storage);
    243         return *get();
    244     }
    245 
    246     T* operator->() const
    247     {
    248         ASSERT(m_storage);
    249         return get();
    250     }
    251 #endif
    252 
    253 private:
    254 #if INSIDE_BLINK
    255     PtrStorage<T>& storage() { return PtrStorage<T>::fromSlot(&m_storage); }
    256     const PtrStorage<T>& storage() const { return PtrStorage<T>::fromSlot(&m_storage); }
    257 #endif
    258 
    259 #if !INSIDE_BLINK
    260     // Disable the assignment operator; we define it above for when
    261     // INSIDE_BLINK is set, but we need to make sure that it is not
    262     // used outside there; the compiler-provided version won't handle reference
    263     // counting properly.
    264     WebPrivatePtr<T>& operator=(const WebPrivatePtr<T>& other);
    265 #endif
    266     // Disable the copy constructor; classes that contain a WebPrivatePtr
    267     // should implement their copy constructor using assign().
    268     WebPrivatePtr(const WebPrivatePtr<T>&);
    269 
    270     void* m_storage;
    271 };
    272 
    273 } // namespace blink
    274 
    275 #endif
    276