1 // Copyright (C) 2014 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "emugl/common/smart_ptr.h" 16 17 #ifdef _WIN32 18 #define WIN32_LEAN_AND_MEAN 19 #include <windows.h> 20 #endif 21 22 namespace emugl { 23 24 // Thread-safe atomic reference-counting type. 25 class RefCount { 26 public: 27 RefCount() : mCount(1) {} 28 ~RefCount() {} 29 30 // Technically not thread-safe, use only for testing. 31 int count() const { return (int)mCount; } 32 33 void increment() { 34 #ifdef _WIN32 35 InterlockedIncrement(&mCount); 36 #else 37 __sync_fetch_and_add(&mCount, 1); 38 #endif 39 } 40 41 bool decrement() { 42 #ifdef _WIN32 43 return InterlockedDecrement(&mCount) == 0; 44 #else 45 return __sync_add_and_fetch(&mCount, -1) == 0; 46 #endif 47 } 48 49 private: 50 #ifdef _WIN32 51 LONG mCount; 52 #else 53 int mCount; 54 #endif 55 }; 56 57 58 // SmartPtrBase implementation. 59 60 SmartPtrBase::SmartPtrBase(void* ptr) : mPtr(ptr), mRefCount(NULL) { 61 if (mPtr) 62 mRefCount = new RefCount(); 63 } 64 65 66 SmartPtrBase::SmartPtrBase(const SmartPtrBase& other) 67 : mPtr(other.mPtr), mRefCount(other.mRefCount) { 68 if (mRefCount) 69 mRefCount->increment(); 70 } 71 72 73 int SmartPtrBase::getRefCount() const { 74 return mRefCount ? mRefCount->count() : 0; 75 } 76 77 78 void SmartPtrBase::addRef() { 79 if (mRefCount) 80 mRefCount->increment(); 81 } 82 83 84 void* SmartPtrBase::copyFrom(const SmartPtrBase& other) { 85 void* old_ptr = release(); 86 87 mPtr = other.mPtr; 88 mRefCount = other.mRefCount; 89 if (mRefCount) 90 mRefCount->increment(); 91 92 return old_ptr; 93 } 94 95 96 void* SmartPtrBase::release() { 97 void* old_ptr = mPtr; 98 RefCount* old_refcount = mRefCount; 99 100 if (old_refcount) { 101 mPtr = NULL; 102 mRefCount = NULL; 103 104 if (old_refcount->decrement()) { 105 delete old_refcount; 106 return old_ptr; 107 } 108 } 109 110 return NULL; 111 } 112 113 } // namespace emugl 114