Home | History | Annotate | Download | only in native
      1 /*
      2  * Copyright (C) 2010 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 UNIQUE_PTR_H_included
     18 #define UNIQUE_PTR_H_included
     19 
     20 #include <cstdlib> // For NULL.
     21 
     22 // This is a fake declaration of std::swap to avoid including <algorithm>
     23 namespace std {
     24 template <class T> void swap(T&, T&);
     25 }
     26 
     27 // Default deleter for pointer types.
     28 template <typename T>
     29 struct DefaultDelete {
     30     enum { type_must_be_complete = sizeof(T) };
     31     DefaultDelete() {}
     32     void operator()(T* p) const {
     33         delete p;
     34     }
     35 };
     36 
     37 // Default deleter for array types.
     38 template <typename T>
     39 struct DefaultDelete<T[]> {
     40     enum { type_must_be_complete = sizeof(T) };
     41     void operator()(T* p) const {
     42         delete[] p;
     43     }
     44 };
     45 
     46 // A smart pointer that deletes the given pointer on destruction.
     47 // Equivalent to C++0x's std::unique_ptr (a combination of boost::scoped_ptr
     48 // and boost::scoped_array).
     49 // Named to be in keeping with Android style but also to avoid
     50 // collision with any other implementation, until we can switch over
     51 // to unique_ptr.
     52 // Use thus:
     53 //   UniquePtr<C> c(new C);
     54 template <typename T, typename D = DefaultDelete<T> >
     55 class UniquePtr {
     56 public:
     57     // Construct a new UniquePtr, taking ownership of the given raw pointer.
     58     explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) {
     59     }
     60 
     61     ~UniquePtr() {
     62         reset();
     63     }
     64 
     65     // Accessors.
     66     T& operator*() const { return *mPtr; }
     67     T* operator->() const { return mPtr; }
     68     T* get() const { return mPtr; }
     69 
     70     // Returns the raw pointer and hands over ownership to the caller.
     71     // The pointer will not be deleted by UniquePtr.
     72     T* release() __attribute__((warn_unused_result)) {
     73         T* result = mPtr;
     74         mPtr = NULL;
     75         return result;
     76     }
     77 
     78     // Takes ownership of the given raw pointer.
     79     // If this smart pointer previously owned a different raw pointer, that
     80     // raw pointer will be freed.
     81     void reset(T* ptr = NULL) {
     82         if (ptr != mPtr) {
     83             D()(mPtr);
     84             mPtr = ptr;
     85         }
     86     }
     87 
     88     // Swap with another unique pointer.
     89     void swap(UniquePtr<T>& other) {
     90       std::swap(mPtr, other.mPtr);
     91     }
     92 
     93 private:
     94     // The raw pointer.
     95     T* mPtr;
     96 
     97     // Comparing unique pointers is probably a mistake, since they're unique.
     98     template <typename T2> bool operator==(const UniquePtr<T2>& p) const;
     99     template <typename T2> bool operator!=(const UniquePtr<T2>& p) const;
    100 
    101     // Disallow copy and assignment.
    102     UniquePtr(const UniquePtr&);
    103     void operator=(const UniquePtr&);
    104 };
    105 
    106 // Partial specialization for array types. Like std::unique_ptr, this removes
    107 // operator* and operator-> but adds operator[].
    108 template <typename T, typename D>
    109 class UniquePtr<T[], D> {
    110 public:
    111     explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) {
    112     }
    113 
    114     ~UniquePtr() {
    115         reset();
    116     }
    117 
    118     T& operator[](size_t i) const {
    119         return mPtr[i];
    120     }
    121     T* get() const { return mPtr; }
    122 
    123     T* release() __attribute__((warn_unused_result)) {
    124         T* result = mPtr;
    125         mPtr = NULL;
    126         return result;
    127     }
    128 
    129     void reset(T* ptr = NULL) {
    130         if (ptr != mPtr) {
    131             D()(mPtr);
    132             mPtr = ptr;
    133         }
    134     }
    135 
    136 private:
    137     T* mPtr;
    138 
    139     // Disallow copy and assignment.
    140     UniquePtr(const UniquePtr&);
    141     void operator=(const UniquePtr&);
    142 };
    143 
    144 #if UNIQUE_PTR_TESTS
    145 
    146 // Run these tests with:
    147 // g++ -g -DUNIQUE_PTR_TESTS -x c++ UniquePtr.h && ./a.out
    148 
    149 #include <stdio.h>
    150 
    151 static void assert(bool b) {
    152     if (!b) {
    153         fprintf(stderr, "FAIL\n");
    154         abort();
    155     }
    156     fprintf(stderr, "OK\n");
    157 }
    158 static int cCount = 0;
    159 struct C {
    160     C() { ++cCount; }
    161     ~C() { --cCount; }
    162 };
    163 static bool freed = false;
    164 struct Freer {
    165     void operator()(int* p) {
    166         assert(*p == 123);
    167         free(p);
    168         freed = true;
    169     }
    170 };
    171 
    172 int main(int argc, char* argv[]) {
    173     //
    174     // UniquePtr<T> tests...
    175     //
    176 
    177     // Can we free a single object?
    178     {
    179         UniquePtr<C> c(new C);
    180         assert(cCount == 1);
    181     }
    182     assert(cCount == 0);
    183     // Does release work?
    184     C* rawC;
    185     {
    186         UniquePtr<C> c(new C);
    187         assert(cCount == 1);
    188         rawC = c.release();
    189     }
    190     assert(cCount == 1);
    191     delete rawC;
    192     // Does reset work?
    193     {
    194         UniquePtr<C> c(new C);
    195         assert(cCount == 1);
    196         c.reset(new C);
    197         assert(cCount == 1);
    198     }
    199     assert(cCount == 0);
    200 
    201     //
    202     // UniquePtr<T[]> tests...
    203     //
    204 
    205     // Can we free an array?
    206     {
    207         UniquePtr<C[]> cs(new C[4]);
    208         assert(cCount == 4);
    209     }
    210     assert(cCount == 0);
    211     // Does release work?
    212     {
    213         UniquePtr<C[]> c(new C[4]);
    214         assert(cCount == 4);
    215         rawC = c.release();
    216     }
    217     assert(cCount == 4);
    218     delete[] rawC;
    219     // Does reset work?
    220     {
    221         UniquePtr<C[]> c(new C[4]);
    222         assert(cCount == 4);
    223         c.reset(new C[2]);
    224         assert(cCount == 2);
    225     }
    226     assert(cCount == 0);
    227 
    228     //
    229     // Custom deleter tests...
    230     //
    231     assert(!freed);
    232     {
    233         UniquePtr<int, Freer> i(reinterpret_cast<int*>(malloc(sizeof(int))));
    234         *i = 123;
    235     }
    236     assert(freed);
    237     return 0;
    238 }
    239 #endif
    240 
    241 #endif  // UNIQUE_PTR_H_included
    242