1464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com/* 2464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * Copyright 2011 Google Inc. All Rights Reserved. 3464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * 4464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * Licensed under the Apache License, Version 2.0 (the "License"); 5464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * you may not use this file except in compliance with the License. 6464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * You may obtain a copy of the License at 7464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * 8464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * http://www.apache.org/licenses/LICENSE-2.0 9464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * 10464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * Unless required by applicable law or agreed to in writing, software 11464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * distributed under the License is distributed on an "AS IS" BASIS, 12464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * See the License for the specific language governing permissions and 14464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * limitations under the License. 15464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com */ 16464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 17464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// Object reference count and smart pointer implementation. 18050736d52301766cd6bd3838766575dab3944551arthurhsu@google.com 19050736d52301766cd6bd3838766575dab3944551arthurhsu@google.com// Smart pointer usage in sfntly: 20050736d52301766cd6bd3838766575dab3944551arthurhsu@google.com// 21050736d52301766cd6bd3838766575dab3944551arthurhsu@google.com// sfntly carries a smart pointer implementation like COM. Ref-countable object 22050736d52301766cd6bd3838766575dab3944551arthurhsu@google.com// type inherits from RefCounted<>, which have AddRef and Release just like 23050736d52301766cd6bd3838766575dab3944551arthurhsu@google.com// IUnknown (but no QueryInterface). Use a Ptr<> based smart pointer to hold 24050736d52301766cd6bd3838766575dab3944551arthurhsu@google.com// the object so that the object ref count is handled correctly. 25050736d52301766cd6bd3838766575dab3944551arthurhsu@google.com// 26050736d52301766cd6bd3838766575dab3944551arthurhsu@google.com// class Foo : public RefCounted<Foo> { 27050736d52301766cd6bd3838766575dab3944551arthurhsu@google.com// public: 28050736d52301766cd6bd3838766575dab3944551arthurhsu@google.com// static Foo* CreateInstance() { 29050736d52301766cd6bd3838766575dab3944551arthurhsu@google.com// Ptr<Foo> obj = new Foo(); // ref count = 1 30246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com// return obj.Detach(); 31050736d52301766cd6bd3838766575dab3944551arthurhsu@google.com// } 32050736d52301766cd6bd3838766575dab3944551arthurhsu@google.com// }; 33050736d52301766cd6bd3838766575dab3944551arthurhsu@google.com// typedef Ptr<Foo> FooPtr; // common short-hand notation 34050736d52301766cd6bd3838766575dab3944551arthurhsu@google.com// FooPtr obj; 35246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com// obj.Attach(Foo::CreatedInstance()); // ref count = 1 36050736d52301766cd6bd3838766575dab3944551arthurhsu@google.com// { 37050736d52301766cd6bd3838766575dab3944551arthurhsu@google.com// FooPtr obj2 = obj; // ref count = 2 38050736d52301766cd6bd3838766575dab3944551arthurhsu@google.com// } // ref count = 1, obj2 out of scope 39246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com// obj.Release(); // ref count = 0, object destroyed 40050736d52301766cd6bd3838766575dab3944551arthurhsu@google.com 41464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// Notes on usage: 42464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// 1. Virtual inherit from RefCount interface in base class if smart pointers 43464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// are going to be defined. 44464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// 2. All RefCounted objects must be instantiated on the heap. Allocating the 45464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// object on stack will cause crash. 46464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// 3. Be careful when you have complex inheritance. For example, 47464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// class A : public RefCounted<A>; 48464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// class B : public A, public RefCounted<B>; 49464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// In this case the smart pointer is pretty dumb and don't count on it to 50464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// nicely destroy your objects as designed. Try refactor your code like 51464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// class I; // the common interface and implementations 52464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// class A : public I, public RefCounted<A>; // A specific implementation 53464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// class B : public I, public RefCounted<B>; // B specific implementation 54464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// 4. Smart pointers here are very bad candidates for function parameters. Use 55464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// dumb pointers in function parameter list. 56464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// 5. When down_cast is performed on a dangling pointer due to bugs in code, 57464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// VC++ will generate SEH which is not handled well in VC++ debugger. One 58464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// can use WinDBG to run it and get the faulting stack. 59464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// 6. Idioms for heap object as return value 60246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com// Foo* createFoo() { FooPtr obj = new Foo(); return obj.Detach(); } 61464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// Foo* passthru() { FooPtr obj = createFoo(), return obj; } 62464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// FooPtr end_scope_pointer; 63246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com// end_scope_pointer.Attach(passThrough); 64464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// If you are not passing that object back, you are the end of scope. 65464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 665af34fd773f8cfee82321393504f558ddf67c628arthurhsu@google.com#ifndef SFNTLY_CPP_SRC_SFNTLY_PORT_REFCOUNT_H_ 675af34fd773f8cfee82321393504f558ddf67c628arthurhsu@google.com#define SFNTLY_CPP_SRC_SFNTLY_PORT_REFCOUNT_H_ 68464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 69464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#if !defined (NDEBUG) 70464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com #define ENABLE_OBJECT_COUNTER 71464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// #define REF_COUNT_DEBUGGING 72464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#endif 73464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 74464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#if defined (REF_COUNT_DEBUGGING) 75464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com #include <stdio.h> 76464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com #include <typeinfo> 77464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#endif 78464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 79464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#include "sfntly/port/atomic.h" 80464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#include "sfntly/port/type.h" 81464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 82464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// Special tag for functions that requires caller to attach instead of using 83464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// assignment operators. 84464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#define CALLER_ATTACH 85464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 86464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#if defined (REF_COUNT_DEBUGGING) 87464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com #define DEBUG_OUTPUT(a) \ 88464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com fprintf(stderr, "%s%s:oc=%d,oid=%d,rc=%d\n", a, \ 89464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com typeid(this).name(), object_counter_, object_id_, ref_count_) 90464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#else 91464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com #define DEBUG_OUTPUT(a) 92464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#endif 93464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 94464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#if defined (_MSC_VER) 95464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com // VC 2008/2010 incorrectly gives this warning for pure virtual functions 96464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com // in virtual inheritance. The only way to get around it is to disable it. 97464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com #pragma warning(disable:4250) 98464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#endif 99464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 100464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comnamespace sfntly { 101464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 102464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comclass RefCount { 103464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com public: 104464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com // Make gcc -Wnon-virtual-dtor happy. 105464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com virtual ~RefCount() {} 106246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com 107246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com virtual size_t AddRef() const = 0; 108246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com virtual size_t Release() const = 0; 109464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}; 110464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 111464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comtemplate <typename T> 112464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comclass NoAddRefRelease : public T { 113464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com public: 114464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com NoAddRefRelease(); 115464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com ~NoAddRefRelease(); 116464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 117464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com private: 118246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com virtual size_t AddRef() const = 0; 119246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com virtual size_t Release() const = 0; 120464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}; 121464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 122464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comtemplate <typename TDerived> 123464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comclass RefCounted : virtual public RefCount { 124464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com public: 125464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com RefCounted() : ref_count_(0) { 126464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#if defined (ENABLE_OBJECT_COUNTER) 127246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com object_id_ = AtomicIncrement(&next_id_); 128246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com AtomicIncrement(&object_counter_); 129464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com DEBUG_OUTPUT("C "); 130464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#endif 131464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 132464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com RefCounted(const RefCounted<TDerived>&) : ref_count_(0) {} 133464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com virtual ~RefCounted() { 134464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#if defined (ENABLE_OBJECT_COUNTER) 135246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com AtomicDecrement(&object_counter_); 136464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com DEBUG_OUTPUT("D "); 137464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#endif 138464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 139464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 140464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com RefCounted<TDerived>& operator=(const RefCounted<TDerived>&) { 141464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com // Each object maintains own ref count, don't propagate. 142464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com return *this; 143464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 144464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 145246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com virtual size_t AddRef() const { 146246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com size_t new_count = AtomicIncrement(&ref_count_); 147464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com DEBUG_OUTPUT("A "); 148464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com return new_count; 149464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 150464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 151246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com virtual size_t Release() const { 152246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com size_t new_ref_count = AtomicDecrement(&ref_count_); 153464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com DEBUG_OUTPUT("R "); 154464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com if (new_ref_count == 0) { 155464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com // A C-style is used to cast away const-ness and to derived. 156464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com // lint does not like this but this is how it works. 157464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com delete (TDerived*)(this); 158464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 159464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com return new_ref_count; 160464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 161464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 162464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com mutable size_t ref_count_; // reference count of current object 163464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#if defined (ENABLE_OBJECT_COUNTER) 164464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com static size_t object_counter_; 165464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com static size_t next_id_; 166464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com mutable size_t object_id_; 167464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#endif 168464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}; 169464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 170464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#if defined (ENABLE_OBJECT_COUNTER) 171464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comtemplate <typename TDerived> size_t RefCounted<TDerived>::object_counter_ = 0; 172464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comtemplate <typename TDerived> size_t RefCounted<TDerived>::next_id_ = 0; 173464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#endif 174464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 175464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com// semi-smart pointer for RefCount derived objects, similar to CComPtr 176464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comtemplate <typename T> 177464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comclass Ptr { 178464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com public: 179464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com Ptr() : p_(NULL) { 180464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 181464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 182464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com // This constructor shall not be explicit. 183464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com // lint does not like this but this is how it works. 184464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com Ptr(T* pT) : p_(NULL) { 185464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com *this = pT; 186464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 187464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 188464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com Ptr(const Ptr<T>& p) : p_(NULL) { 189464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com *this = p; 190464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 191464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 192464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com ~Ptr() { 193246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com Release(); 194464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 195464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 196464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com T* operator=(T* pT) { 197464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com if (p_ == pT) { 198464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com return p_; 199464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 200464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com if (pT) { 201464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com RefCount* p = static_cast<RefCount*>(pT); 202464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com if (p == NULL) { 203464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com return NULL; 204464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 205246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com p->AddRef(); // always AddRef() before Release() 206464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 207246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com Release(); 208464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com p_ = pT; 209464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com return p_; 210464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 211464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 212464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com T* operator=(const Ptr<T>& p) { 213464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com if (p_ == p.p_) { 214464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com return p_; 215464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 216464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com return operator=(p.p_); 217464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 218464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 219464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com operator T*&() { 220464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com return p_; 221464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 222464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 223464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com T& operator*() const { 224464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com return *p_; // It can throw! 225464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 226464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 227464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com NoAddRefRelease<T>* operator->() const { 228464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com return (NoAddRefRelease<T>*)p_; // It can throw! 229464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 230464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 231464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com bool operator!() const { 232464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com return (p_ == NULL); 233464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 234464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 235464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com bool operator<(const Ptr<T>& p) const { 236464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com return (p_ < p.p_); 237464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 238464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 239464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com bool operator!=(T* pT) const { 240464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com return !operator==(pT); 241464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 242464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 243464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com bool operator==(T* pT) const { 244464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com return (p_ == pT); 245464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 246464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 247246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com size_t Release() const { 248464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com size_t ref_count = 0; 249464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com if (p_) { 250464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com RefCount* p = static_cast<RefCount*>(p_); 251464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com if (p) { 252246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com ref_count = p->Release(); 253464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 254464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com p_ = NULL; 255464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 256464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com return ref_count; 257464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 258464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 259246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com void Attach(T* pT) { 260464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com if (p_ != pT) { 261246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com Release(); 262464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com p_ = pT; 263464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 264464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 265464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 266246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com T* Detach() { 267464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com T* pT = p_; 268464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com p_ = NULL; 269464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com return pT; 270464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com } 271464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 272464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com mutable T* p_; 273464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}; 274464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 275464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com} // namespace sfntly 276464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com 2775af34fd773f8cfee82321393504f558ddf67c628arthurhsu@google.com#endif // SFNTLY_CPP_SRC_SFNTLY_PORT_REFCOUNT_H_ 278