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