media/omx-plugin/include/ics/utils/RefBase.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial