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(PassRefPtr<WeakReference<T> > ref) : m_ref(ref) { }
     89 
     90     T* get() const { return m_ref ? m_ref->get() : 0; }
     91 
     92     typedef RefPtr<WeakReference<T> > (WeakPtr::*UnspecifiedBoolType);
     93     operator UnspecifiedBoolType() const { return get() ? &WeakPtr::m_ref : 0; }
     94 
     95 private:
     96     RefPtr<WeakReference<T> > m_ref;
     97 };
     98 
     99 template<typename T>
    100 class WeakPtrFactory {
    101     WTF_MAKE_NONCOPYABLE(WeakPtrFactory<T>);
    102     WTF_MAKE_FAST_ALLOCATED;
    103 public:
    104     explicit WeakPtrFactory(T* ptr) : m_ref(WeakReference<T>::create(ptr)) { }
    105 
    106     WeakPtrFactory(PassRefPtr<WeakReference<T> > ref, T* ptr)
    107         : m_ref(ref)
    108     {
    109         m_ref->bindTo(ptr);
    110     }
    111 
    112     ~WeakPtrFactory() { m_ref->clear(); }
    113 
    114     // We should consider having createWeakPtr populate m_ref the first time createWeakPtr is called.
    115     WeakPtr<T> createWeakPtr() { return WeakPtr<T>(m_ref); }
    116 
    117     void revokeAll()
    118     {
    119         T* ptr = m_ref->get();
    120         m_ref->clear();
    121         // We create a new WeakReference so that future calls to createWeakPtr() create nonzero WeakPtrs.
    122         m_ref = WeakReference<T>::create(ptr);
    123     }
    124 
    125 private:
    126     RefPtr<WeakReference<T> > m_ref;
    127 };
    128 
    129 } // namespace WTF
    130 
    131 using WTF::WeakPtr;
    132 using WTF::WeakPtrFactory;
    133 using WTF::WeakReference;
    134 
    135 #endif
    136