1/* 2 * Copyright (C) 2013 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#ifndef RS_REF_BASE_H 18#define RS_REF_BASE_H 19 20 21#include <stdint.h> 22#include <sys/types.h> 23#include <stdlib.h> 24#include <string.h> 25 26#include "StrongPointer.h" 27#include "TypeHelpers.h" 28 29// --------------------------------------------------------------------------- 30namespace android{ 31namespace RSC { 32 33class TextOutput; 34TextOutput& printWeakPointer(TextOutput& to, const void* val); 35 36// --------------------------------------------------------------------------- 37 38#define COMPARE_WEAK(_op_) \ 39inline bool operator _op_ (const sp<T>& o) const { \ 40 return m_ptr _op_ o.m_ptr; \ 41} \ 42inline bool operator _op_ (const T* o) const { \ 43 return m_ptr _op_ o; \ 44} \ 45template<typename U> \ 46inline bool operator _op_ (const sp<U>& o) const { \ 47 return m_ptr _op_ o.m_ptr; \ 48} \ 49template<typename U> \ 50inline bool operator _op_ (const U* o) const { \ 51 return m_ptr _op_ o; \ 52} 53 54// --------------------------------------------------------------------------- 55class ReferenceMover; 56class ReferenceConverterBase { 57public: 58 virtual size_t getReferenceTypeSize() const = 0; 59 virtual void* getReferenceBase(void const*) const = 0; 60 inline virtual ~ReferenceConverterBase() { } 61}; 62 63// --------------------------------------------------------------------------- 64 65class RefBase 66{ 67public: 68 void incStrong(const void* id) const; 69 void decStrong(const void* id) const; 70 71 void forceIncStrong(const void* id) const; 72 73 //! DEBUGGING ONLY: Get current strong ref count. 74 int32_t getStrongCount() const; 75 76 class weakref_type 77 { 78 public: 79 RefBase* refBase() const; 80 81 void incWeak(const void* id); 82 void decWeak(const void* id); 83 84 // acquires a strong reference if there is already one. 85 bool attemptIncStrong(const void* id); 86 87 // acquires a weak reference if there is already one. 88 // This is not always safe. see ProcessState.cpp and BpBinder.cpp 89 // for proper use. 90 bool attemptIncWeak(const void* id); 91 92 //! DEBUGGING ONLY: Get current weak ref count. 93 int32_t getWeakCount() const; 94 95 //! DEBUGGING ONLY: Print references held on object. 96 void printRefs() const; 97 98 //! DEBUGGING ONLY: Enable tracking for this object. 99 // enable -- enable/disable tracking 100 // retain -- when tracking is enable, if true, then we save a stack trace 101 // for each reference and dereference; when retain == false, we 102 // match up references and dereferences and keep only the 103 // outstanding ones. 104 105 void trackMe(bool enable, bool retain); 106 }; 107 108 weakref_type* createWeak(const void* id) const; 109 110 weakref_type* getWeakRefs() const; 111 112 //! DEBUGGING ONLY: Print references held on object. 113 inline void printRefs() const { getWeakRefs()->printRefs(); } 114 115 //! DEBUGGING ONLY: Enable tracking of object. 116 inline void trackMe(bool enable, bool retain) 117 { 118 getWeakRefs()->trackMe(enable, retain); 119 } 120 121 typedef RefBase basetype; 122 123protected: 124 RefBase(); 125 virtual ~RefBase(); 126 127 //! Flags for extendObjectLifetime() 128 enum { 129 OBJECT_LIFETIME_STRONG = 0x0000, 130 OBJECT_LIFETIME_WEAK = 0x0001, 131 OBJECT_LIFETIME_MASK = 0x0001 132 }; 133 134 void extendObjectLifetime(int32_t mode); 135 136 //! Flags for onIncStrongAttempted() 137 enum { 138 FIRST_INC_STRONG = 0x0001 139 }; 140 141 virtual void onFirstRef(); 142 virtual void onLastStrongRef(const void* id); 143 virtual bool onIncStrongAttempted(uint32_t flags, const void* id); 144 virtual void onLastWeakRef(const void* id); 145 146private: 147 friend class ReferenceMover; 148 static void moveReferences(void* d, void const* s, size_t n, 149 const ReferenceConverterBase& caster); 150 151private: 152 friend class weakref_type; 153 class weakref_impl; 154 155 RefBase(const RefBase& o); 156 RefBase& operator=(const RefBase& o); 157 158 weakref_impl* const mRefs; 159}; 160 161// --------------------------------------------------------------------------- 162 163template <class T> 164class LightRefBase 165{ 166public: 167 inline LightRefBase() : mCount(0) { } 168 inline void incStrong(__attribute__((unused)) const void* id) const { 169 __sync_fetch_and_add(&mCount, 1); 170 } 171 inline void decStrong(__attribute__((unused)) const void* id) const { 172 if (__sync_fetch_and_sub(&mCount, 1) == 1) { 173 delete static_cast<const T*>(this); 174 } 175 } 176 //! DEBUGGING ONLY: Get current strong ref count. 177 inline int32_t getStrongCount() const { 178 return mCount; 179 } 180 181 typedef LightRefBase<T> basetype; 182 183protected: 184 inline ~LightRefBase() { } 185 186private: 187 friend class ReferenceMover; 188 inline static void moveReferences(void*, void const*, size_t, 189 const ReferenceConverterBase&) { } 190 191private: 192 mutable volatile int32_t mCount; 193}; 194 195// --------------------------------------------------------------------------- 196 197template <typename T> 198class wp 199{ 200public: 201 typedef typename RefBase::weakref_type weakref_type; 202 203 inline wp() : m_ptr(0) { } 204 205 wp(T* other); 206 wp(const wp<T>& other); 207 wp(const sp<T>& other); 208 template<typename U> wp(U* other); 209 template<typename U> wp(const sp<U>& other); 210 template<typename U> wp(const wp<U>& other); 211 212 ~wp(); 213 214 // Assignment 215 216 wp& operator = (T* other); 217 wp& operator = (const wp<T>& other); 218 wp& operator = (const sp<T>& other); 219 220 template<typename U> wp& operator = (U* other); 221 template<typename U> wp& operator = (const wp<U>& other); 222 template<typename U> wp& operator = (const sp<U>& other); 223 224 void set_object_and_refs(T* other, weakref_type* refs); 225 226 // promotion to sp 227 228 sp<T> promote() const; 229 230 // Reset 231 232 void clear(); 233 234 // Accessors 235 236 inline weakref_type* get_refs() const { return m_refs; } 237 238 inline T* unsafe_get() const { return m_ptr; } 239 240 // Operators 241 242 COMPARE_WEAK(==) 243 COMPARE_WEAK(!=) 244 COMPARE_WEAK(>) 245 COMPARE_WEAK(<) 246 COMPARE_WEAK(<=) 247 COMPARE_WEAK(>=) 248 249 inline bool operator == (const wp<T>& o) const { 250 return (m_ptr == o.m_ptr) && (m_refs == o.m_refs); 251 } 252 template<typename U> 253 inline bool operator == (const wp<U>& o) const { 254 return m_ptr == o.m_ptr; 255 } 256 257 inline bool operator > (const wp<T>& o) const { 258 return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr); 259 } 260 template<typename U> 261 inline bool operator > (const wp<U>& o) const { 262 return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr); 263 } 264 265 inline bool operator < (const wp<T>& o) const { 266 return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr); 267 } 268 template<typename U> 269 inline bool operator < (const wp<U>& o) const { 270 return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr); 271 } 272 inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; } 273 template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); } 274 inline bool operator <= (const wp<T>& o) const { return !operator > (o); } 275 template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); } 276 inline bool operator >= (const wp<T>& o) const { return !operator < (o); } 277 template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); } 278 279private: 280 template<typename Y> friend class sp; 281 template<typename Y> friend class wp; 282 283 T* m_ptr; 284 weakref_type* m_refs; 285}; 286 287template <typename T> 288TextOutput& operator<<(TextOutput& to, const wp<T>& val); 289 290#undef COMPARE_WEAK 291 292// --------------------------------------------------------------------------- 293// No user serviceable parts below here. 294 295template<typename T> 296wp<T>::wp(T* other) 297 : m_ptr(other) 298{ 299 if (other) m_refs = other->createWeak(this); 300} 301 302template<typename T> 303wp<T>::wp(const wp<T>& other) 304 : m_ptr(other.m_ptr), m_refs(other.m_refs) 305{ 306 if (m_ptr) m_refs->incWeak(this); 307} 308 309template<typename T> 310wp<T>::wp(const sp<T>& other) 311 : m_ptr(other.m_ptr) 312{ 313 if (m_ptr) { 314 m_refs = m_ptr->createWeak(this); 315 } 316} 317 318template<typename T> template<typename U> 319wp<T>::wp(U* other) 320 : m_ptr(other) 321{ 322 if (other) m_refs = other->createWeak(this); 323} 324 325template<typename T> template<typename U> 326wp<T>::wp(const wp<U>& other) 327 : m_ptr(other.m_ptr) 328{ 329 if (m_ptr) { 330 m_refs = other.m_refs; 331 m_refs->incWeak(this); 332 } 333} 334 335template<typename T> template<typename U> 336wp<T>::wp(const sp<U>& other) 337 : m_ptr(other.m_ptr) 338{ 339 if (m_ptr) { 340 m_refs = m_ptr->createWeak(this); 341 } 342} 343 344template<typename T> 345wp<T>::~wp() 346{ 347 if (m_ptr) m_refs->decWeak(this); 348} 349 350template<typename T> 351wp<T>& wp<T>::operator = (T* other) 352{ 353 weakref_type* newRefs = 354 other ? other->createWeak(this) : 0; 355 if (m_ptr) m_refs->decWeak(this); 356 m_ptr = other; 357 m_refs = newRefs; 358 return *this; 359} 360 361template<typename T> 362wp<T>& wp<T>::operator = (const wp<T>& other) 363{ 364 weakref_type* otherRefs(other.m_refs); 365 T* otherPtr(other.m_ptr); 366 if (otherPtr) otherRefs->incWeak(this); 367 if (m_ptr) m_refs->decWeak(this); 368 m_ptr = otherPtr; 369 m_refs = otherRefs; 370 return *this; 371} 372 373template<typename T> 374wp<T>& wp<T>::operator = (const sp<T>& other) 375{ 376 weakref_type* newRefs = 377 other != NULL ? other->createWeak(this) : 0; 378 T* otherPtr(other.m_ptr); 379 if (m_ptr) m_refs->decWeak(this); 380 m_ptr = otherPtr; 381 m_refs = newRefs; 382 return *this; 383} 384 385template<typename T> template<typename U> 386wp<T>& wp<T>::operator = (U* other) 387{ 388 weakref_type* newRefs = 389 other ? other->createWeak(this) : 0; 390 if (m_ptr) m_refs->decWeak(this); 391 m_ptr = other; 392 m_refs = newRefs; 393 return *this; 394} 395 396template<typename T> template<typename U> 397wp<T>& wp<T>::operator = (const wp<U>& other) 398{ 399 weakref_type* otherRefs(other.m_refs); 400 U* otherPtr(other.m_ptr); 401 if (otherPtr) otherRefs->incWeak(this); 402 if (m_ptr) m_refs->decWeak(this); 403 m_ptr = otherPtr; 404 m_refs = otherRefs; 405 return *this; 406} 407 408template<typename T> template<typename U> 409wp<T>& wp<T>::operator = (const sp<U>& other) 410{ 411 weakref_type* newRefs = 412 other != NULL ? other->createWeak(this) : 0; 413 U* otherPtr(other.m_ptr); 414 if (m_ptr) m_refs->decWeak(this); 415 m_ptr = otherPtr; 416 m_refs = newRefs; 417 return *this; 418} 419 420template<typename T> 421void wp<T>::set_object_and_refs(T* other, weakref_type* refs) 422{ 423 if (other) refs->incWeak(this); 424 if (m_ptr) m_refs->decWeak(this); 425 m_ptr = other; 426 m_refs = refs; 427} 428 429template<typename T> 430sp<T> wp<T>::promote() const 431{ 432 sp<T> result; 433 if (m_ptr && m_refs->attemptIncStrong(&result)) { 434 result.set_pointer(m_ptr); 435 } 436 return result; 437} 438 439template<typename T> 440void wp<T>::clear() 441{ 442 if (m_ptr) { 443 m_refs->decWeak(this); 444 m_ptr = 0; 445 } 446} 447 448template <typename T> 449inline TextOutput& operator<<(TextOutput& to, const wp<T>& val) 450{ 451 return printWeakPointer(to, val.unsafe_get()); 452} 453 454// --------------------------------------------------------------------------- 455 456// this class just serves as a namespace so TYPE::moveReferences can stay 457// private. 458 459class ReferenceMover { 460 // StrongReferenceCast and WeakReferenceCast do the impedance matching 461 // between the generic (void*) implementation in Refbase and the strongly typed 462 // template specializations below. 463 464 template <typename TYPE> 465 struct StrongReferenceCast : public ReferenceConverterBase { 466 virtual size_t getReferenceTypeSize() const { return sizeof( sp<TYPE> ); } 467 virtual void* getReferenceBase(void const* p) const { 468 sp<TYPE> const* sptr(reinterpret_cast<sp<TYPE> const*>(p)); 469 return static_cast<typename TYPE::basetype *>(sptr->get()); 470 } 471 }; 472 473 template <typename TYPE> 474 struct WeakReferenceCast : public ReferenceConverterBase { 475 virtual size_t getReferenceTypeSize() const { return sizeof( wp<TYPE> ); } 476 virtual void* getReferenceBase(void const* p) const { 477 wp<TYPE> const* sptr(reinterpret_cast<wp<TYPE> const*>(p)); 478 return static_cast<typename TYPE::basetype *>(sptr->unsafe_get()); 479 } 480 }; 481 482public: 483 template<typename TYPE> static inline 484 void move_references(sp<TYPE>* d, sp<TYPE> const* s, size_t n) { 485 memmove(d, s, n*sizeof(sp<TYPE>)); 486 StrongReferenceCast<TYPE> caster; 487 TYPE::moveReferences(d, s, n, caster); 488 } 489 template<typename TYPE> static inline 490 void move_references(wp<TYPE>* d, wp<TYPE> const* s, size_t n) { 491 memmove(d, s, n*sizeof(wp<TYPE>)); 492 WeakReferenceCast<TYPE> caster; 493 TYPE::moveReferences(d, s, n, caster); 494 } 495}; 496 497// specialization for moving sp<> and wp<> types. 498// these are used by the [Sorted|Keyed]Vector<> implementations 499// sp<> and wp<> need to be handled specially, because they do not 500// have trivial copy operation in the general case (see RefBase.cpp 501// when DEBUG ops are enabled), but can be implemented very 502// efficiently in most cases. 503 504template<typename TYPE> inline 505void move_forward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) { 506 ReferenceMover::move_references(d, s, n); 507} 508 509template<typename TYPE> inline 510void move_backward_type(sp<TYPE>* d, sp<TYPE> const* s, size_t n) { 511 ReferenceMover::move_references(d, s, n); 512} 513 514template<typename TYPE> inline 515void move_forward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) { 516 ReferenceMover::move_references(d, s, n); 517} 518 519template<typename TYPE> inline 520void move_backward_type(wp<TYPE>* d, wp<TYPE> const* s, size_t n) { 521 ReferenceMover::move_references(d, s, n); 522} 523 524 525}; // namespace RSC 526}; // namespace android 527// --------------------------------------------------------------------------- 528 529#endif // RS_REF_BASE_H 530