Home | History | Annotate | Download | only in common
      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