Home | History | Annotate | Download | only in wtf
      1 /*
      2  * Copyright (C) 2013 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
      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_WeakPtr_h
     27 #define WTF_WeakPtr_h
     28 
     29 #include "wtf/Noncopyable.h"
     30 #include "wtf/PassRefPtr.h"
     31 #include "wtf/RefPtr.h"
     32 #include "wtf/ThreadSafeRefCounted.h"
     33 #include "wtf/Threading.h"
     34 
     35 namespace WTF {
     36 
     37 template<typename T>
     38 class WeakReference : public ThreadSafeRefCounted<WeakReference<T> > {
     39     WTF_MAKE_NONCOPYABLE(WeakReference<T>);
     40     WTF_MAKE_FAST_ALLOCATED;
     41 public:
     42     static PassRefPtr<WeakReference<T> > create(T* ptr) { return adoptRef(new WeakReference(ptr)); }
     43     static PassRefPtr<WeakReference<T> > createUnbound() { return adoptRef(new WeakReference()); }
     44 
     45     T* get() const
     46     {
     47         ASSERT(m_boundThread == currentThread());
     48         return m_ptr;
     49     }
     50 
     51     void clear()
     52     {
     53         ASSERT(m_boundThread == currentThread());
     54         m_ptr = 0;
     55     }
     56 
     57     void bindTo(T* ptr)
     58     {
     59         ASSERT(!m_ptr);
     60 #ifndef NDEBUG
     61         m_boundThread = currentThread();
     62 #endif
     63         m_ptr = ptr;
     64     }
     65 
     66 private:
     67     WeakReference() : m_ptr(0) { }
     68 
     69     explicit WeakReference(T* ptr)
     70         : m_ptr(ptr)
     71 #ifndef NDEBUG
     72         , m_boundThread(currentThread())
     73 #endif
     74     {
     75     }
     76 
     77     T* m_ptr;
     78 #ifndef NDEBUG
     79     ThreadIdentifier m_boundThread;
     80 #endif
     81 };
     82 
     83 template<typename T>
     84 class WeakPtr {
     85     WTF_MAKE_FAST_ALLOCATED;
     86 public:
     87     WeakPtr() { }
     88     WeakPtr(std::nullptr_t) { }
     89     WeakPtr(PassRefPtr<WeakReference<T> > ref) : m_ref(ref) { }
     90 
     91     T* get() const { return m_ref ? m_ref->get() : 0; }
     92     void clear() { m_ref.clear(); }
     93 
     94     T* operator->() const
     95     {
     96         ASSERT(get());
     97         return get();
     98     }
     99 
    100     typedef RefPtr<WeakReference<T> > (WeakPtr::*UnspecifiedBoolType);
    101     operator UnspecifiedBoolType() const { return get() ? &WeakPtr::m_ref : 0; }
    102 
    103 private:
    104     RefPtr<WeakReference<T> > m_ref;
    105 };
    106 
    107 template<typename T, typename U> inline bool operator==(const WeakPtr<T>& a, const WeakPtr<U>& b)
    108 {
    109     return a.get() == b.get();
    110 }
    111 
    112 template<typename T, typename U> inline bool operator!=(const WeakPtr<T>& a, const WeakPtr<U>& b)
    113 {
    114     return a.get() != b.get();
    115 }
    116 
    117 template<typename T>
    118 class WeakPtrFactory {
    119     WTF_MAKE_NONCOPYABLE(WeakPtrFactory<T>);
    120     WTF_MAKE_FAST_ALLOCATED;
    121 public:
    122     explicit WeakPtrFactory(T* ptr) : m_ref(WeakReference<T>::create(ptr)) { }
    123 
    124     WeakPtrFactory(PassRefPtr<WeakReference<T> > ref, T* ptr)
    125         : m_ref(ref)
    126     {
    127         m_ref->bindTo(ptr);
    128     }
    129 
    130     ~WeakPtrFactory() { m_ref->clear(); }
    131 
    132     // We should consider having createWeakPtr populate m_ref the first time createWeakPtr is called.
    133     WeakPtr<T> createWeakPtr() { return WeakPtr<T>(m_ref); }
    134 
    135     void revokeAll()
    136     {
    137         T* ptr = m_ref->get();
    138         m_ref->clear();
    139         // We create a new WeakReference so that future calls to createWeakPtr() create nonzero WeakPtrs.
    140         m_ref = WeakReference<T>::create(ptr);
    141     }
    142 
    143 private:
    144     RefPtr<WeakReference<T> > m_ref;
    145 };
    146 
    147 } // namespace WTF
    148 
    149 using WTF::WeakPtr;
    150 using WTF::WeakPtrFactory;
    151 using WTF::WeakReference;
    152 
    153 #endif
    154