• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 2016 The Android Open Source Project
3   *
4   * Licensed under the Apache License, Version 2.0 (the "License");
5   * you may not use this file except in compliance with the License.
6   * You may obtain a copy of the License at
7   *
8   *      http://www.apache.org/licenses/LICENSE-2.0
9   *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  
18  // SOME COMMENTS ABOUT USAGE:
19  
20  // This provides primarily wp<> weak pointer types and RefBase, which work
21  // together with sp<> from <StrongPointer.h>.
22  
23  // sp<> (and wp<>) are a type of smart pointer that use a well defined protocol
24  // to operate. As long as the object they are templated with implements that
25  // protocol, these smart pointers work. In several places the platform
26  // instantiates sp<> with non-RefBase objects; the two are not tied to each
27  // other.
28  
29  // RefBase is such an implementation and it supports strong pointers, weak
30  // pointers and some magic features for the binder.
31  
32  // So, when using RefBase objects, you have the ability to use strong and weak
33  // pointers through sp<> and wp<>.
34  
35  // Normally, when the last strong pointer goes away, the object is destroyed,
36  // i.e. it's destructor is called. HOWEVER, parts of its associated memory is not
37  // freed until the last weak pointer is released.
38  
39  // Weak pointers are essentially "safe" pointers. They are always safe to
40  // access through promote(). They may return nullptr if the object was
41  // destroyed because it ran out of strong pointers. This makes them good candidates
42  // for keys in a cache for instance.
43  
44  // Weak pointers remain valid for comparison purposes even after the underlying
45  // object has been destroyed. Even if object A is destroyed and its memory reused
46  // for B, A remaining weak pointer to A will not compare equal to one to B.
47  // This again makes them attractive for use as keys.
48  
49  // How is this supposed / intended to be used?
50  
51  // Our recommendation is to use strong references (sp<>) when there is an
52  // ownership relation. e.g. when an object "owns" another one, use a strong
53  // ref. And of course use strong refs as arguments of functions (it's extremely
54  // rare that a function will take a wp<>).
55  
56  // Typically a newly allocated object will immediately be used to initialize
57  // a strong pointer, which may then be used to construct or assign to other
58  // strong and weak pointers.
59  
60  // Use weak references when there are no ownership relation. e.g. the keys in a
61  // cache (you cannot use plain pointers because there is no safe way to acquire
62  // a strong reference from a vanilla pointer).
63  
64  // This implies that two objects should never (or very rarely) have sp<> on
65  // each other, because they can't both own each other.
66  
67  
68  // Caveats with reference counting
69  
70  // Obviously, circular strong references are a big problem; this creates leaks
71  // and it's hard to debug -- except it's in fact really easy because RefBase has
72  // tons of debugging code for that. It can basically tell you exactly where the
73  // leak is.
74  
75  // Another problem has to do with destructors with side effects. You must
76  // assume that the destructor of reference counted objects can be called AT ANY
77  // TIME. For instance code as simple as this:
78  
79  // void setStuff(const sp<Stuff>& stuff) {
80  //   std::lock_guard<std::mutex> lock(mMutex);
81  //   mStuff = stuff;
82  // }
83  
84  // is very dangerous. This code WILL deadlock one day or another.
85  
86  // What isn't obvious is that ~Stuff() can be called as a result of the
87  // assignment. And it gets called with the lock held. First of all, the lock is
88  // protecting mStuff, not ~Stuff(). Secondly, if ~Stuff() uses its own internal
89  // mutex, now you have mutex ordering issues.  Even worse, if ~Stuff() is
90  // virtual, now you're calling into "user" code (potentially), by that, I mean,
91  // code you didn't even write.
92  
93  // A correct way to write this code is something like:
94  
95  // void setStuff(const sp<Stuff>& stuff) {
96  //   std::unique_lock<std::mutex> lock(mMutex);
97  //   sp<Stuff> hold = mStuff;
98  //   mStuff = stuff;
99  //   lock.unlock();
100  // }
101  
102  // More importantly, reference counted objects should do as little work as
103  // possible in their destructor, or at least be mindful that their destructor
104  // could be called from very weird and unintended places.
105  
106  // Other more specific restrictions for wp<> and sp<>:
107  
108  // Do not construct a strong pointer to "this" in an object's constructor.
109  // The onFirstRef() callback would be made on an incompletely constructed
110  // object.
111  // Construction of a weak pointer to "this" in an object's constructor is also
112  // discouraged. But the implementation was recently changed so that, in the
113  // absence of extendObjectLifetime() calls, weak pointers no longer impact
114  // object lifetime, and hence this no longer risks premature deallocation,
115  // and hence usually works correctly.
116  
117  // Such strong or weak pointers can be safely created in the RefBase onFirstRef()
118  // callback.
119  
120  // Use of wp::unsafe_get() for any purpose other than debugging is almost
121  // always wrong.  Unless you somehow know that there is a longer-lived sp<> to
122  // the same object, it may well return a pointer to a deallocated object that
123  // has since been reallocated for a different purpose. (And if you know there
124  // is a longer-lived sp<>, why not use an sp<> directly?) A wp<> should only be
125  // dereferenced by using promote().
126  
127  // Any object inheriting from RefBase should always be destroyed as the result
128  // of a reference count decrement, not via any other means.  Such objects
129  // should never be stack allocated, or appear directly as data members in other
130  // objects. Objects inheriting from RefBase should have their strong reference
131  // count incremented as soon as possible after construction. Usually this
132  // will be done via construction of an sp<> to the object, but may instead
133  // involve other means of calling RefBase::incStrong().
134  // Explicitly deleting or otherwise destroying a RefBase object with outstanding
135  // wp<> or sp<> pointers to it will result in an abort or heap corruption.
136  
137  // It is particularly important not to mix sp<> and direct storage management
138  // since the sp from raw pointer constructor is implicit. Thus if a RefBase-
139  // -derived object of type T is managed without ever incrementing its strong
140  // count, and accidentally passed to f(sp<T>), a strong pointer to the object
141  // will be temporarily constructed and destroyed, prematurely deallocating the
142  // object, and resulting in heap corruption. None of this would be easily
143  // visible in the source.
144  
145  // Extra Features:
146  
147  // RefBase::extendObjectLifetime() can be used to prevent destruction of the
148  // object while there are still weak references. This is really special purpose
149  // functionality to support Binder.
150  
151  // Wp::promote(), implemented via the attemptIncStrong() member function, is
152  // used to try to convert a weak pointer back to a strong pointer.  It's the
153  // normal way to try to access the fields of an object referenced only through
154  // a wp<>.  Binder code also sometimes uses attemptIncStrong() directly.
155  
156  // RefBase provides a number of additional callbacks for certain reference count
157  // events, as well as some debugging facilities.
158  
159  // Debugging support can be enabled by turning on DEBUG_REFS in RefBase.cpp.
160  // Otherwise little checking is provided.
161  
162  // Thread safety:
163  
164  // Like std::shared_ptr, sp<> and wp<> allow concurrent accesses to DIFFERENT
165  // sp<> and wp<> instances that happen to refer to the same underlying object.
166  // They do NOT support concurrent access (where at least one access is a write)
167  // to THE SAME sp<> or wp<>.  In effect, their thread-safety properties are
168  // exactly like those of T*, NOT atomic<T*>.
169  
170  #ifndef ANDROID_REF_BASE_H
171  #define ANDROID_REF_BASE_H
172  
173  #include <atomic>
174  
175  #include <stdint.h>
176  #include <sys/types.h>
177  #include <stdlib.h>
178  #include <string.h>
179  
180  // LightRefBase used to be declared in this header, so we have to include it
181  #include <utils/LightRefBase.h>
182  
183  #include <utils/StrongPointer.h>
184  #include <utils/TypeHelpers.h>
185  
186  // ---------------------------------------------------------------------------
187  namespace android {
188  
189  class TextOutput;
190  TextOutput& printWeakPointer(TextOutput& to, const void* val);
191  
192  // ---------------------------------------------------------------------------
193  
194  #define COMPARE_WEAK(_op_)                                      \
195  inline bool operator _op_ (const sp<T>& o) const {              \
196      return m_ptr _op_ o.m_ptr;                                  \
197  }                                                               \
198  inline bool operator _op_ (const T* o) const {                  \
199      return m_ptr _op_ o;                                        \
200  }                                                               \
201  template<typename U>                                            \
202  inline bool operator _op_ (const sp<U>& o) const {              \
203      return m_ptr _op_ o.m_ptr;                                  \
204  }                                                               \
205  template<typename U>                                            \
206  inline bool operator _op_ (const U* o) const {                  \
207      return m_ptr _op_ o;                                        \
208  }
209  
210  // ---------------------------------------------------------------------------
211  
212  // RefererenceRenamer is pure abstract, there is no virtual method
213  // implementation to put in a translation unit in order to silence the
214  // weak vtables warning.
215  #if defined(__clang__)
216  #pragma clang diagnostic push
217  #pragma clang diagnostic ignored "-Wweak-vtables"
218  #endif
219  
220  class ReferenceRenamer {
221  protected:
222      // destructor is purposely not virtual so we avoid code overhead from
223      // subclasses; we have to make it protected to guarantee that it
224      // cannot be called from this base class (and to make strict compilers
225      // happy).
~ReferenceRenamer()226      ~ReferenceRenamer() { }
227  public:
228      virtual void operator()(size_t i) const = 0;
229  };
230  
231  #if defined(__clang__)
232  #pragma clang diagnostic pop
233  #endif
234  
235  // ---------------------------------------------------------------------------
236  
237  class RefBase
238  {
239  public:
240              void            incStrong(const void* id) const;
241              void            decStrong(const void* id) const;
242  
243              void            forceIncStrong(const void* id) const;
244  
245              //! DEBUGGING ONLY: Get current strong ref count.
246              int32_t         getStrongCount() const;
247  
248      class weakref_type
249      {
250      public:
251          RefBase*            refBase() const;
252  
253          void                incWeak(const void* id);
254          void                decWeak(const void* id);
255  
256          // acquires a strong reference if there is already one.
257          bool                attemptIncStrong(const void* id);
258  
259          // acquires a weak reference if there is already one.
260          // This is not always safe. see ProcessState.cpp and BpBinder.cpp
261          // for proper use.
262          bool                attemptIncWeak(const void* id);
263  
264          //! DEBUGGING ONLY: Get current weak ref count.
265          int32_t             getWeakCount() const;
266  
267          //! DEBUGGING ONLY: Print references held on object.
268          void                printRefs() const;
269  
270          //! DEBUGGING ONLY: Enable tracking for this object.
271          // enable -- enable/disable tracking
272          // retain -- when tracking is enable, if true, then we save a stack trace
273          //           for each reference and dereference; when retain == false, we
274          //           match up references and dereferences and keep only the
275          //           outstanding ones.
276  
277          void                trackMe(bool enable, bool retain);
278      };
279  
280              weakref_type*   createWeak(const void* id) const;
281  
282              weakref_type*   getWeakRefs() const;
283  
284              //! DEBUGGING ONLY: Print references held on object.
printRefs()285      inline  void            printRefs() const { getWeakRefs()->printRefs(); }
286  
287              //! DEBUGGING ONLY: Enable tracking of object.
trackMe(bool enable,bool retain)288      inline  void            trackMe(bool enable, bool retain)
289      {
290          getWeakRefs()->trackMe(enable, retain);
291      }
292  
293      typedef RefBase basetype;
294  
295  protected:
296                              RefBase();
297      virtual                 ~RefBase();
298  
299      //! Flags for extendObjectLifetime()
300      enum {
301          OBJECT_LIFETIME_STRONG  = 0x0000,
302          OBJECT_LIFETIME_WEAK    = 0x0001,
303          OBJECT_LIFETIME_MASK    = 0x0001
304      };
305  
306              void            extendObjectLifetime(int32_t mode);
307  
308      //! Flags for onIncStrongAttempted()
309      enum {
310          FIRST_INC_STRONG = 0x0001
311      };
312  
313      // Invoked after creation of initial strong pointer/reference.
314      virtual void            onFirstRef();
315      // Invoked when either the last strong reference goes away, or we need to undo
316      // the effect of an unnecessary onIncStrongAttempted.
317      virtual void            onLastStrongRef(const void* id);
318      // Only called in OBJECT_LIFETIME_WEAK case.  Returns true if OK to promote to
319      // strong reference. May have side effects if it returns true.
320      // The first flags argument is always FIRST_INC_STRONG.
321      // TODO: Remove initial flag argument.
322      virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);
323      // Invoked in the OBJECT_LIFETIME_WEAK case when the last reference of either
324      // kind goes away.  Unused.
325      // TODO: Remove.
326      virtual void            onLastWeakRef(const void* id);
327  
328  private:
329      friend class weakref_type;
330      class weakref_impl;
331  
332                              RefBase(const RefBase& o);
333              RefBase&        operator=(const RefBase& o);
334  
335  private:
336      friend class ReferenceMover;
337  
338      static void renameRefs(size_t n, const ReferenceRenamer& renamer);
339  
340      static void renameRefId(weakref_type* ref,
341              const void* old_id, const void* new_id);
342  
343      static void renameRefId(RefBase* ref,
344              const void* old_id, const void* new_id);
345  
346          weakref_impl* const mRefs;
347  };
348  
349  // ---------------------------------------------------------------------------
350  
351  template <typename T>
352  class wp
353  {
354  public:
355      typedef typename RefBase::weakref_type weakref_type;
356  
wp()357      inline wp() : m_ptr(0) { }
358  
359      wp(T* other);  // NOLINT(implicit)
360      wp(const wp<T>& other);
361      explicit wp(const sp<T>& other);
362      template<typename U> wp(U* other);  // NOLINT(implicit)
363      template<typename U> wp(const sp<U>& other);  // NOLINT(implicit)
364      template<typename U> wp(const wp<U>& other);  // NOLINT(implicit)
365  
366      ~wp();
367  
368      // Assignment
369  
370      wp& operator = (T* other);
371      wp& operator = (const wp<T>& other);
372      wp& operator = (const sp<T>& other);
373  
374      template<typename U> wp& operator = (U* other);
375      template<typename U> wp& operator = (const wp<U>& other);
376      template<typename U> wp& operator = (const sp<U>& other);
377  
378      void set_object_and_refs(T* other, weakref_type* refs);
379  
380      // promotion to sp
381  
382      sp<T> promote() const;
383  
384      // Reset
385  
386      void clear();
387  
388      // Accessors
389  
get_refs()390      inline  weakref_type* get_refs() const { return m_refs; }
391  
unsafe_get()392      inline  T* unsafe_get() const { return m_ptr; }
393  
394      // Operators
395  
396      COMPARE_WEAK(==)
397      COMPARE_WEAK(!=)
398      COMPARE_WEAK(>)
399      COMPARE_WEAK(<)
400      COMPARE_WEAK(<=)
401      COMPARE_WEAK(>=)
402  
403      inline bool operator == (const wp<T>& o) const {
404          return (m_ptr == o.m_ptr) && (m_refs == o.m_refs);
405      }
406      template<typename U>
407      inline bool operator == (const wp<U>& o) const {
408          return m_ptr == o.m_ptr;
409      }
410  
411      inline bool operator > (const wp<T>& o) const {
412          return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
413      }
414      template<typename U>
415      inline bool operator > (const wp<U>& o) const {
416          return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
417      }
418  
419      inline bool operator < (const wp<T>& o) const {
420          return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
421      }
422      template<typename U>
423      inline bool operator < (const wp<U>& o) const {
424          return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
425      }
426                           inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; }
427      template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
428                           inline bool operator <= (const wp<T>& o) const { return !operator > (o); }
429      template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
430                           inline bool operator >= (const wp<T>& o) const { return !operator < (o); }
431      template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
432  
433  private:
434      template<typename Y> friend class sp;
435      template<typename Y> friend class wp;
436  
437      T*              m_ptr;
438      weakref_type*   m_refs;
439  };
440  
441  template <typename T>
442  TextOutput& operator<<(TextOutput& to, const wp<T>& val);
443  
444  #undef COMPARE_WEAK
445  
446  // ---------------------------------------------------------------------------
447  // No user serviceable parts below here.
448  
449  template<typename T>
wp(T * other)450  wp<T>::wp(T* other)
451      : m_ptr(other)
452  {
453      if (other) m_refs = other->createWeak(this);
454  }
455  
456  template<typename T>
wp(const wp<T> & other)457  wp<T>::wp(const wp<T>& other)
458      : m_ptr(other.m_ptr), m_refs(other.m_refs)
459  {
460      if (m_ptr) m_refs->incWeak(this);
461  }
462  
463  template<typename T>
wp(const sp<T> & other)464  wp<T>::wp(const sp<T>& other)
465      : m_ptr(other.m_ptr)
466  {
467      if (m_ptr) {
468          m_refs = m_ptr->createWeak(this);
469      }
470  }
471  
472  template<typename T> template<typename U>
wp(U * other)473  wp<T>::wp(U* other)
474      : m_ptr(other)
475  {
476      if (other) m_refs = other->createWeak(this);
477  }
478  
479  template<typename T> template<typename U>
wp(const wp<U> & other)480  wp<T>::wp(const wp<U>& other)
481      : m_ptr(other.m_ptr)
482  {
483      if (m_ptr) {
484          m_refs = other.m_refs;
485          m_refs->incWeak(this);
486      }
487  }
488  
489  template<typename T> template<typename U>
wp(const sp<U> & other)490  wp<T>::wp(const sp<U>& other)
491      : m_ptr(other.m_ptr)
492  {
493      if (m_ptr) {
494          m_refs = m_ptr->createWeak(this);
495      }
496  }
497  
498  template<typename T>
~wp()499  wp<T>::~wp()
500  {
501      if (m_ptr) m_refs->decWeak(this);
502  }
503  
504  template<typename T>
505  wp<T>& wp<T>::operator = (T* other)
506  {
507      weakref_type* newRefs =
508          other ? other->createWeak(this) : 0;
509      if (m_ptr) m_refs->decWeak(this);
510      m_ptr = other;
511      m_refs = newRefs;
512      return *this;
513  }
514  
515  template<typename T>
516  wp<T>& wp<T>::operator = (const wp<T>& other)
517  {
518      weakref_type* otherRefs(other.m_refs);
519      T* otherPtr(other.m_ptr);
520      if (otherPtr) otherRefs->incWeak(this);
521      if (m_ptr) m_refs->decWeak(this);
522      m_ptr = otherPtr;
523      m_refs = otherRefs;
524      return *this;
525  }
526  
527  template<typename T>
528  wp<T>& wp<T>::operator = (const sp<T>& other)
529  {
530      weakref_type* newRefs =
531          other != NULL ? other->createWeak(this) : 0;
532      T* otherPtr(other.m_ptr);
533      if (m_ptr) m_refs->decWeak(this);
534      m_ptr = otherPtr;
535      m_refs = newRefs;
536      return *this;
537  }
538  
539  template<typename T> template<typename U>
540  wp<T>& wp<T>::operator = (U* other)
541  {
542      weakref_type* newRefs =
543          other ? other->createWeak(this) : 0;
544      if (m_ptr) m_refs->decWeak(this);
545      m_ptr = other;
546      m_refs = newRefs;
547      return *this;
548  }
549  
550  template<typename T> template<typename U>
551  wp<T>& wp<T>::operator = (const wp<U>& other)
552  {
553      weakref_type* otherRefs(other.m_refs);
554      U* otherPtr(other.m_ptr);
555      if (otherPtr) otherRefs->incWeak(this);
556      if (m_ptr) m_refs->decWeak(this);
557      m_ptr = otherPtr;
558      m_refs = otherRefs;
559      return *this;
560  }
561  
562  template<typename T> template<typename U>
563  wp<T>& wp<T>::operator = (const sp<U>& other)
564  {
565      weakref_type* newRefs =
566          other != NULL ? other->createWeak(this) : 0;
567      U* otherPtr(other.m_ptr);
568      if (m_ptr) m_refs->decWeak(this);
569      m_ptr = otherPtr;
570      m_refs = newRefs;
571      return *this;
572  }
573  
574  template<typename T>
set_object_and_refs(T * other,weakref_type * refs)575  void wp<T>::set_object_and_refs(T* other, weakref_type* refs)
576  {
577      if (other) refs->incWeak(this);
578      if (m_ptr) m_refs->decWeak(this);
579      m_ptr = other;
580      m_refs = refs;
581  }
582  
583  template<typename T>
promote()584  sp<T> wp<T>::promote() const
585  {
586      sp<T> result;
587      if (m_ptr && m_refs->attemptIncStrong(&result)) {
588          result.set_pointer(m_ptr);
589      }
590      return result;
591  }
592  
593  template<typename T>
clear()594  void wp<T>::clear()
595  {
596      if (m_ptr) {
597          m_refs->decWeak(this);
598          m_ptr = 0;
599      }
600  }
601  
602  template <typename T>
603  inline TextOutput& operator<<(TextOutput& to, const wp<T>& val)
604  {
605      return printWeakPointer(to, val.unsafe_get());
606  }
607  
608  // ---------------------------------------------------------------------------
609  
610  // this class just serves as a namespace so TYPE::moveReferences can stay
611  // private.
612  class ReferenceMover {
613  public:
614      // it would be nice if we could make sure no extra code is generated
615      // for sp<TYPE> or wp<TYPE> when TYPE is a descendant of RefBase:
616      // Using a sp<RefBase> override doesn't work; it's a bit like we wanted
617      // a template<typename TYPE inherits RefBase> template...
618  
619      template<typename TYPE> static inline
move_references(sp<TYPE> * dest,sp<TYPE> const * src,size_t n)620      void move_references(sp<TYPE>* dest, sp<TYPE> const* src, size_t n) {
621  
622          class Renamer : public ReferenceRenamer {
623              sp<TYPE>* d_;
624              sp<TYPE> const* s_;
625              virtual void operator()(size_t i) const {
626                  // The id are known to be the sp<>'s this pointer
627                  TYPE::renameRefId(d_[i].get(), &s_[i], &d_[i]);
628              }
629          public:
630              Renamer(sp<TYPE>* d, sp<TYPE> const* s) : d_(d), s_(s) { }
631              virtual ~Renamer() { }
632          };
633  
634          memmove(dest, src, n*sizeof(sp<TYPE>));
635          TYPE::renameRefs(n, Renamer(dest, src));
636      }
637  
638  
639      template<typename TYPE> static inline
move_references(wp<TYPE> * dest,wp<TYPE> const * src,size_t n)640      void move_references(wp<TYPE>* dest, wp<TYPE> const* src, size_t n) {
641  
642          class Renamer : public ReferenceRenamer {
643              wp<TYPE>* d_;
644              wp<TYPE> const* s_;
645              virtual void operator()(size_t i) const {
646                  // The id are known to be the wp<>'s this pointer
647                  TYPE::renameRefId(d_[i].get_refs(), &s_[i], &d_[i]);
648              }
649          public:
650              Renamer(wp<TYPE>* rd, wp<TYPE> const* rs) : d_(rd), s_(rs) { }
651              virtual ~Renamer() { }
652          };
653  
654          memmove(dest, src, n*sizeof(wp<TYPE>));
655          TYPE::renameRefs(n, Renamer(dest, src));
656      }
657  };
658  
659  // specialization for moving sp<> and wp<> types.
660  // these are used by the [Sorted|Keyed]Vector<> implementations
661  // sp<> and wp<> need to be handled specially, because they do not
662  // have trivial copy operation in the general case (see RefBase.cpp
663  // when DEBUG ops are enabled), but can be implemented very
664  // efficiently in most cases.
665  
666  template<typename TYPE> inline
move_forward_type(sp<TYPE> * d,sp<TYPE> const * s,size_t n)667  void move_forward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
668      ReferenceMover::move_references(d, s, n);
669  }
670  
671  template<typename TYPE> inline
move_backward_type(sp<TYPE> * d,sp<TYPE> const * s,size_t n)672  void move_backward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) {
673      ReferenceMover::move_references(d, s, n);
674  }
675  
676  template<typename TYPE> inline
move_forward_type(wp<TYPE> * d,wp<TYPE> const * s,size_t n)677  void move_forward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
678      ReferenceMover::move_references(d, s, n);
679  }
680  
681  template<typename TYPE> inline
move_backward_type(wp<TYPE> * d,wp<TYPE> const * s,size_t n)682  void move_backward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) {
683      ReferenceMover::move_references(d, s, n);
684  }
685  
686  }; // namespace android
687  
688  // ---------------------------------------------------------------------------
689  
690  #endif // ANDROID_REF_BASE_H
691