Coverage Report

Created: 2024-11-20 12:56

/root/doris/be/src/gutil/gscoped_ptr.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE.txt file.
4
5
// Scopers help you manage ownership of a pointer, helping you easily manage the
6
// a pointer within a scope, and automatically destroying the pointer at the
7
// end of a scope.  There are two main classes you will use, which correspond
8
// to the operators new/delete and new[]/delete[].
9
//
10
// Example usage (gscoped_ptr):
11
//   {
12
//     gscoped_ptr<Foo> foo(new Foo("wee"));
13
//   }  // foo goes out of scope, releasing the pointer with it.
14
//
15
//   {
16
//     gscoped_ptr<Foo> foo;          // No pointer managed.
17
//     foo.reset(new Foo("wee"));    // Now a pointer is managed.
18
//     foo.reset(new Foo("wee2"));   // Foo("wee") was destroyed.
19
//     foo.reset(new Foo("wee3"));   // Foo("wee2") was destroyed.
20
//     foo->Method();                // Foo::Method() called.
21
//     foo.get()->Method();          // Foo::Method() called.
22
//     SomeFunc(foo.release());      // SomeFunc takes ownership, foo no longer
23
//                                   // manages a pointer.
24
//     foo.reset(new Foo("wee4"));   // foo manages a pointer again.
25
//     foo.reset();                  // Foo("wee4") destroyed, foo no longer
26
//                                   // manages a pointer.
27
//   }  // foo wasn't managing a pointer, so nothing was destroyed.
28
//
29
// Example usage (gscoped_array):
30
//   {
31
//     gscoped_array<Foo> foo(new Foo[100]);
32
//     foo.get()->Method();  // Foo::Method on the 0th element.
33
//     foo[10].Method();     // Foo::Method on the 10th element.
34
//   }
35
//
36
// These scopers also implement part of the functionality of C++11 unique_ptr
37
// in that they are "movable but not copyable."  You can use the scopers in
38
// the parameter and return types of functions to signify ownership transfer
39
// in to and out of a function.  When calling a function that has a scoper
40
// as the argument type, it must be called with the result of an analogous
41
// scoper's Pass() function or another function that generates a temporary;
42
// passing by copy will NOT work.  Here is an example using gscoped_ptr:
43
//
44
//   void TakesOwnership(gscoped_ptr<Foo> arg) {
45
//     // Do something with arg
46
//   }
47
//   gscoped_ptr<Foo> CreateFoo() {
48
//     // No need for calling Pass() because we are constructing a temporary
49
//     // for the return value.
50
//     return gscoped_ptr<Foo>(new Foo("new"));
51
//   }
52
//   gscoped_ptr<Foo> PassThru(gscoped_ptr<Foo> arg) {
53
//     return std::move(arg);
54
//   }
55
//
56
//   {
57
//     gscoped_ptr<Foo> ptr(new Foo("yay"));  // ptr manages Foo("yay").
58
//     TakesOwnership(std::move(ptr));           // ptr no longer owns Foo("yay").
59
//     gscoped_ptr<Foo> ptr2 = CreateFoo();   // ptr2 owns the return Foo.
60
//     gscoped_ptr<Foo> ptr3 =                // ptr3 now owns what was in ptr2.
61
//         PassThru(std::move(ptr2));            // ptr2 is correspondingly NULL.
62
//   }
63
//
64
// Notice that if you do not call Pass() when returning from PassThru(), or
65
// when invoking TakesOwnership(), the code will not compile because scopers
66
// are not copyable; they only implement move semantics which require calling
67
// the Pass() function to signify a destructive transfer of state. CreateFoo()
68
// is different though because we are constructing a temporary on the return
69
// line and thus can avoid needing to call Pass().
70
//
71
// Pass() properly handles upcast in assignment, i.e. you can assign
72
// gscoped_ptr<Child> to gscoped_ptr<Parent>:
73
//
74
//   gscoped_ptr<Foo> foo(new Foo());
75
//   gscoped_ptr<FooParent> parent = std::move(foo);
76
//
77
// PassAs<>() should be used to upcast return value in return statement:
78
//
79
//   gscoped_ptr<Foo> CreateFoo() {
80
//     gscoped_ptr<FooChild> result(new FooChild());
81
//     return result.PassAs<Foo>();
82
//   }
83
//
84
// Note that PassAs<>() is implemented only for gscoped_ptr, but not for
85
// gscoped_array. This is because casting array pointers may not be safe.
86
//
87
// -------------------------------------------------------------------------
88
// Cloudera notes: this should be used in preference to std::unique_ptr since
89
// it offers a ::release() method like unique_ptr. We unfortunately cannot
90
// just use unique_ptr because it has an inconsistent implementation in
91
// some of the older compilers we have to support.
92
// -------------------------------------------------------------------------
93
94
// This is an implementation designed to match the anticipated future TR2
95
// implementation of the scoped_ptr class, and its closely-related brethren,
96
// scoped_array, scoped_ptr_malloc.
97
98
#pragma once
99
100
#include <assert.h>
101
#include <stddef.h>
102
#include <stdlib.h>
103
104
#include <algorithm> // For std::swap().
105
#include <type_traits>
106
107
#include "gutil/basictypes.h"
108
#include "gutil/move.h"
109
#include "gutil/template_util.h"
110
111
namespace doris {
112
113
namespace subtle {
114
class RefCountedBase;
115
class RefCountedThreadSafeBase;
116
} // namespace subtle
117
118
// Function object which deletes its parameter, which must be a pointer.
119
// If C is an array type, invokes 'delete[]' on the parameter; otherwise,
120
// invokes 'delete'. The default deleter for gscoped_ptr<T>.
121
template <class T>
122
struct DefaultDeleter {
123
    DefaultDeleter() {}
124
    template <typename U>
125
    DefaultDeleter(const DefaultDeleter<U>& other) {
126
        // IMPLEMENTATION NOTE: C++11 20.7.1.1.2p2 only provides this constructor
127
        // if U* is implicitly convertible to T* and U is not an array type.
128
        //
129
        // Correct implementation should use SFINAE to disable this
130
        // constructor. However, since there are no other 1-argument constructors,
131
        // using a COMPILE_ASSERT() based on is_convertible<> and requiring
132
        // complete types is simpler and will cause compile failures for equivalent
133
        // misuses.
134
        //
135
        // Note, the is_convertible<U*, T*> check also ensures that U is not an
136
        // array. T is guaranteed to be a non-array, so any U* where U is an array
137
        // cannot convert to T*.
138
        enum { T_must_be_complete = sizeof(T) };
139
        enum { U_must_be_complete = sizeof(U) };
140
        COMPILE_ASSERT((std::is_convertible<U*, T*>::value),
141
                       U_ptr_must_implicitly_convert_to_T_ptr);
142
    }
143
    inline void operator()(T* ptr) const {
144
        enum { type_must_be_complete = sizeof(T) };
145
        delete ptr;
146
    }
147
};
148
149
// Specialization of DefaultDeleter for array types.
150
template <class T>
151
struct DefaultDeleter<T[]> {
152
    inline void operator()(T* ptr) const {
153
        enum { type_must_be_complete = sizeof(T) };
154
        delete[] ptr;
155
    }
156
157
private:
158
    // Disable this operator for any U != T because it is undefined to execute
159
    // an array delete when the static type of the array mismatches the dynamic
160
    // type.
161
    //
162
    // References:
163
    //   C++98 [expr.delete]p3
164
    //   http://cplusplus.github.com/LWG/lwg-defects.html#938
165
    template <typename U>
166
    void operator()(U* array) const;
167
};
168
169
template <class T, int n>
170
struct DefaultDeleter<T[n]> {
171
    // Never allow someone to declare something like gscoped_ptr<int[10]>.
172
    COMPILE_ASSERT(sizeof(T) == -1, do_not_use_array_with_size_as_type);
173
};
174
175
// Function object which invokes 'free' on its parameter, which must be
176
// a pointer. Can be used to store malloc-allocated pointers in gscoped_ptr:
177
//
178
// gscoped_ptr<int, doris::FreeDeleter> foo_ptr(
179
//     static_cast<int*>(malloc(sizeof(int))));
180
struct FreeDeleter {
181
0
    inline void operator()(void* ptr) const { free(ptr); }
182
};
183
184
namespace internal {
185
186
template <typename T>
187
struct IsNotRefCounted {
188
    enum {
189
        value = !std::is_convertible<T*, doris::subtle::RefCountedBase*>::value &&
190
                !std::is_convertible<T*, doris::subtle::RefCountedThreadSafeBase*>::value
191
    };
192
};
193
194
// Minimal implementation of the core logic of gscoped_ptr, suitable for
195
// reuse in both gscoped_ptr and its specializations.
196
template <class T, class D>
197
class gscoped_ptr_impl {
198
public:
199
    explicit gscoped_ptr_impl(T* p) : data_(p) {}
200
201
    // Initializer for deleters that have data parameters.
202
    gscoped_ptr_impl(T* p, const D& d) : data_(p, d) {}
203
204
    // Templated constructor that destructively takes the value from another
205
    // gscoped_ptr_impl.
206
    template <typename U, typename V>
207
    gscoped_ptr_impl(gscoped_ptr_impl<U, V>* other)
208
            : data_(other->release(), other->get_deleter()) {
209
        // We do not support move-only deleters.  We could modify our move
210
        // emulation to have base::subtle::move() and base::subtle::forward()
211
        // functions that are imperfect emulations of their C++11 equivalents,
212
        // but until there's a requirement, just assume deleters are copyable.
213
    }
214
215
    template <typename U, typename V>
216
    void TakeState(gscoped_ptr_impl<U, V>* other) {
217
        // See comment in templated constructor above regarding lack of support
218
        // for move-only deleters.
219
        reset(other->release());
220
        get_deleter() = other->get_deleter();
221
    }
222
223
    ~gscoped_ptr_impl() {
224
        if (data_.ptr != NULL) {
225
            // Not using get_deleter() saves one function call in non-optimized
226
            // builds.
227
            static_cast<D&>(data_)(data_.ptr);
228
        }
229
    }
230
231
    void reset(T* p) {
232
        // This is a self-reset, which is no longer allowed: http://crbug.com/162971
233
        if (p != NULL && p == data_.ptr) abort();
234
235
        // Note that running data_.ptr = p can lead to undefined behavior if
236
        // get_deleter()(get()) deletes this. In order to pevent this, reset()
237
        // should update the stored pointer before deleting its old value.
238
        //
239
        // However, changing reset() to use that behavior may cause current code to
240
        // break in unexpected ways. If the destruction of the owned object
241
        // dereferences the gscoped_ptr when it is destroyed by a call to reset(),
242
        // then it will incorrectly dispatch calls to |p| rather than the original
243
        // value of |data_.ptr|.
244
        //
245
        // During the transition period, set the stored pointer to NULL while
246
        // deleting the object. Eventually, this safety check will be removed to
247
        // prevent the scenario initially described from occuring and
248
        // http://crbug.com/176091 can be closed.
249
        T* old = data_.ptr;
250
        data_.ptr = NULL;
251
        if (old != NULL) static_cast<D&>(data_)(old);
252
        data_.ptr = p;
253
    }
254
255
    T* get() const { return data_.ptr; }
256
257
    D& get_deleter() { return data_; }
258
    const D& get_deleter() const { return data_; }
259
260
    void swap(gscoped_ptr_impl& p2) {
261
        // Standard swap idiom: 'using std::swap' ensures that std::swap is
262
        // present in the overload set, but we call swap unqualified so that
263
        // any more-specific overloads can be used, if available.
264
        using std::swap;
265
        swap(static_cast<D&>(data_), static_cast<D&>(p2.data_));
266
        swap(data_.ptr, p2.data_.ptr);
267
    }
268
269
    T* release() {
270
        T* old_ptr = data_.ptr;
271
        data_.ptr = NULL;
272
        return old_ptr;
273
    }
274
275
private:
276
    // Needed to allow type-converting constructor.
277
    template <typename U, typename V>
278
    friend class gscoped_ptr_impl;
279
280
    // Use the empty base class optimization to allow us to have a D
281
    // member, while avoiding any space overhead for it when D is an
282
    // empty class.  See e.g. http://www.cantrip.org/emptyopt.html for a good
283
    // discussion of this technique.
284
    struct Data : public D {
285
        explicit Data(T* ptr_in) : ptr(ptr_in) {}
286
        Data(T* ptr_in, D other) : D(std::move(other)), ptr(ptr_in) {}
287
        T* ptr;
288
    };
289
290
    Data data_;
291
292
    DISALLOW_COPY_AND_ASSIGN(gscoped_ptr_impl);
293
};
294
295
} // namespace internal
296
297
} // namespace doris
298
299
// A gscoped_ptr<T> is like a T*, except that the destructor of gscoped_ptr<T>
300
// automatically deletes the pointer it holds (if any).
301
// That is, gscoped_ptr<T> owns the T object that it points to.
302
// Like a T*, a gscoped_ptr<T> may hold either NULL or a pointer to a T object.
303
// Also like T*, gscoped_ptr<T> is thread-compatible, and once you
304
// dereference it, you get the thread safety guarantees of T.
305
//
306
// The size of gscoped_ptr is small. On most compilers, when using the
307
// DefaultDeleter, sizeof(gscoped_ptr<T>) == sizeof(T*). Custom deleters will
308
// increase the size proportional to whatever state they need to have. See
309
// comments inside gscoped_ptr_impl<> for details.
310
//
311
// Current implementation targets having a strict subset of  C++11's
312
// unique_ptr<> features. Known deficiencies include not supporting move-only
313
// deleteres, function pointers as deleters, and deleters with reference
314
// types.
315
template <class T, class D = doris::DefaultDeleter<T>>
316
class gscoped_ptr {
317
    MOVE_ONLY_TYPE_FOR_CPP_03(gscoped_ptr, RValue)
318
319
    COMPILE_ASSERT(doris::internal::IsNotRefCounted<T>::value,
320
                   T_is_refcounted_type_and_needs_scoped_refptr);
321
322
public:
323
    // The element and deleter types.
324
    typedef T element_type;
325
    typedef D deleter_type;
326
327
    // Constructor.  Defaults to initializing with NULL.
328
    gscoped_ptr() : impl_(NULL) {}
329
330
    // Constructor.  Takes ownership of p.
331
    explicit gscoped_ptr(element_type* p) : impl_(p) {}
332
333
    // Constructor.  Allows initialization of a stateful deleter.
334
    gscoped_ptr(element_type* p, const D& d) : impl_(p, d) {}
335
336
    // Constructor.  Allows construction from a gscoped_ptr rvalue for a
337
    // convertible type and deleter.
338
    //
339
    // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct
340
    // from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor
341
    // has different post-conditions if D is a reference type. Since this
342
    // implementation does not support deleters with reference type,
343
    // we do not need a separate move constructor allowing us to avoid one
344
    // use of SFINAE. You only need to care about this if you modify the
345
    // implementation of gscoped_ptr.
346
    template <typename U, typename V>
347
    gscoped_ptr(gscoped_ptr<U, V> other) : impl_(&other.impl_) {
348
        COMPILE_ASSERT(!std::is_array<U>::value, U_cannot_be_an_array);
349
    }
350
351
    // Constructor.  Move constructor for C++03 move emulation of this type.
352
    gscoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) {}
353
354
    // operator=.  Allows assignment from a gscoped_ptr rvalue for a convertible
355
    // type and deleter.
356
    //
357
    // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from
358
    // the normal move assignment operator. By C++11 20.7.1.2.3.4, this templated
359
    // form has different requirements on for move-only Deleters. Since this
360
    // implementation does not support move-only Deleters, we do not need a
361
    // separate move assignment operator allowing us to avoid one use of SFINAE.
362
    // You only need to care about this if you modify the implementation of
363
    // gscoped_ptr.
364
    template <typename U, typename V>
365
    gscoped_ptr& operator=(gscoped_ptr<U, V> rhs) {
366
        COMPILE_ASSERT(!std::is_array<U>::value, U_cannot_be_an_array);
367
        impl_.TakeState(&rhs.impl_);
368
        return *this;
369
    }
370
371
    // Reset.  Deletes the currently owned object, if any.
372
    // Then takes ownership of a new object, if given.
373
    void reset(element_type* p = NULL) { impl_.reset(p); }
374
375
    // Accessors to get the owned object.
376
    // operator* and operator-> will assert() if there is no current object.
377
    element_type& operator*() const {
378
        assert(impl_.get() != NULL);
379
        return *impl_.get();
380
    }
381
    element_type* operator->() const {
382
        assert(impl_.get() != NULL);
383
        return impl_.get();
384
    }
385
    element_type* get() const { return impl_.get(); }
386
387
    // Access to the deleter.
388
    deleter_type& get_deleter() { return impl_.get_deleter(); }
389
    const deleter_type& get_deleter() const { return impl_.get_deleter(); }
390
391
    // Allow gscoped_ptr<element_type> to be used in boolean expressions, but not
392
    // implicitly convertible to a real bool (which is dangerous).
393
private:
394
    typedef doris::internal::gscoped_ptr_impl<element_type, deleter_type> gscoped_ptr::*Testable;
395
396
public:
397
    operator Testable() const { return impl_.get() ? &gscoped_ptr::impl_ : NULL; }
398
399
    // Comparison operators.
400
    // These return whether two gscoped_ptr refer to the same object, not just to
401
    // two different but equal objects.
402
    bool operator==(const element_type* p) const { return impl_.get() == p; }
403
    bool operator!=(const element_type* p) const { return impl_.get() != p; }
404
405
    // Swap two scoped pointers.
406
    void swap(gscoped_ptr& p2) { impl_.swap(p2.impl_); }
407
408
    // Release a pointer.
409
    // The return value is the current pointer held by this object.
410
    // If this object holds a NULL pointer, the return value is NULL.
411
    // After this operation, this object will hold a NULL pointer,
412
    // and will not own the object any more.
413
    element_type* release() WARN_UNUSED_RESULT { return impl_.release(); }
414
415
    // C++98 doesn't support functions templates with default parameters which
416
    // makes it hard to write a PassAs() that understands converting the deleter
417
    // while preserving simple calling semantics.
418
    //
419
    // Until there is a use case for PassAs() with custom deleters, just ignore
420
    // the custom deleter.
421
    template <typename PassAsType>
422
    gscoped_ptr<PassAsType> PassAs() {
423
        return gscoped_ptr<PassAsType>(Pass());
424
    }
425
426
private:
427
    // Needed to reach into |impl_| in the constructor.
428
    template <typename U, typename V>
429
    friend class gscoped_ptr;
430
    doris::internal::gscoped_ptr_impl<element_type, deleter_type> impl_;
431
432
    // Forbid comparison of gscoped_ptr types.  If U != T, it totally
433
    // doesn't make sense, and if U == T, it still doesn't make sense
434
    // because you should never have the same object owned by two different
435
    // gscoped_ptrs.
436
    template <class U>
437
    bool operator==(gscoped_ptr<U> const& p2) const;
438
    template <class U>
439
    bool operator!=(gscoped_ptr<U> const& p2) const;
440
};
441
442
template <class T, class D>
443
class gscoped_ptr<T[], D> {
444
    MOVE_ONLY_TYPE_FOR_CPP_03(gscoped_ptr, RValue)
445
446
public:
447
    // The element and deleter types.
448
    typedef T element_type;
449
    typedef D deleter_type;
450
451
    // Constructor.  Defaults to initializing with NULL.
452
    gscoped_ptr() : impl_(NULL) {}
453
454
    // Constructor. Stores the given array. Note that the argument's type
455
    // must exactly match T*. In particular:
456
    // - it cannot be a pointer to a type derived from T, because it is
457
    //   inherently unsafe in the general case to access an array through a
458
    //   pointer whose dynamic type does not match its static type (eg., if
459
    //   T and the derived types had different sizes access would be
460
    //   incorrectly calculated). Deletion is also always undefined
461
    //   (C++98 [expr.delete]p3). If you're doing this, fix your code.
462
    // - it cannot be NULL, because NULL is an integral expression, not a
463
    //   pointer to T. Use the no-argument version instead of explicitly
464
    //   passing NULL.
465
    // - it cannot be const-qualified differently from T per unique_ptr spec
466
    //   (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting
467
    //   to work around this may use implicit_cast<const T*>().
468
    //   However, because of the first bullet in this comment, users MUST
469
    //   NOT use implicit_cast<Base*>() to upcast the static type of the array.
470
    explicit gscoped_ptr(element_type* array) : impl_(array) {}
471
472
    // Constructor.  Move constructor for C++03 move emulation of this type.
473
    gscoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) {}
474
475
    // operator=.  Move operator= for C++03 move emulation of this type.
476
    gscoped_ptr& operator=(RValue rhs) {
477
        impl_.TakeState(&rhs.object->impl_);
478
        return *this;
479
    }
480
481
    // Reset.  Deletes the currently owned array, if any.
482
    // Then takes ownership of a new object, if given.
483
    void reset(element_type* array = NULL) { impl_.reset(array); }
484
485
    // Accessors to get the owned array.
486
    element_type& operator[](size_t i) const {
487
        assert(impl_.get() != NULL);
488
        return impl_.get()[i];
489
    }
490
    element_type* get() const { return impl_.get(); }
491
492
    // Access to the deleter.
493
    deleter_type& get_deleter() { return impl_.get_deleter(); }
494
    const deleter_type& get_deleter() const { return impl_.get_deleter(); }
495
496
    // Allow gscoped_ptr<element_type> to be used in boolean expressions, but not
497
    // implicitly convertible to a real bool (which is dangerous).
498
private:
499
    typedef doris::internal::gscoped_ptr_impl<element_type, deleter_type> gscoped_ptr::*Testable;
500
501
public:
502
    operator Testable() const { return impl_.get() ? &gscoped_ptr::impl_ : NULL; }
503
504
    // Comparison operators.
505
    // These return whether two gscoped_ptr refer to the same object, not just to
506
    // two different but equal objects.
507
    bool operator==(element_type* array) const { return impl_.get() == array; }
508
    bool operator!=(element_type* array) const { return impl_.get() != array; }
509
510
    // Swap two scoped pointers.
511
    void swap(gscoped_ptr& p2) { impl_.swap(p2.impl_); }
512
513
    // Release a pointer.
514
    // The return value is the current pointer held by this object.
515
    // If this object holds a NULL pointer, the return value is NULL.
516
    // After this operation, this object will hold a NULL pointer,
517
    // and will not own the object any more.
518
    element_type* release() WARN_UNUSED_RESULT { return impl_.release(); }
519
520
private:
521
    // Force element_type to be a complete type.
522
    enum { type_must_be_complete = sizeof(element_type) };
523
524
    // Actually hold the data.
525
    doris::internal::gscoped_ptr_impl<element_type, deleter_type> impl_;
526
527
    // Disable initialization from any type other than element_type*, by
528
    // providing a constructor that matches such an initialization, but is
529
    // private and has no definition. This is disabled because it is not safe to
530
    // call delete[] on an array whose static type does not match its dynamic
531
    // type.
532
    template <typename U>
533
    explicit gscoped_ptr(U* array);
534
    explicit gscoped_ptr(int disallow_construction_from_null);
535
536
    // Disable reset() from any type other than element_type*, for the same
537
    // reasons as the constructor above.
538
    template <typename U>
539
    void reset(U* array);
540
    void reset(int disallow_reset_from_null);
541
542
    // Forbid comparison of gscoped_ptr types.  If U != T, it totally
543
    // doesn't make sense, and if U == T, it still doesn't make sense
544
    // because you should never have the same object owned by two different
545
    // gscoped_ptrs.
546
    template <class U>
547
    bool operator==(gscoped_ptr<U> const& p2) const;
548
    template <class U>
549
    bool operator!=(gscoped_ptr<U> const& p2) const;
550
};
551
552
// Free functions
553
template <class T, class D>
554
void swap(gscoped_ptr<T, D>& p1, gscoped_ptr<T, D>& p2) {
555
    p1.swap(p2);
556
}
557
558
template <class T, class D>
559
bool operator==(T* p1, const gscoped_ptr<T, D>& p2) {
560
    return p1 == p2.get();
561
}
562
563
template <class T, class D>
564
bool operator!=(T* p1, const gscoped_ptr<T, D>& p2) {
565
    return p1 != p2.get();
566
}
567
568
// DEPRECATED: Use gscoped_ptr<C[]> instead.
569
//
570
// gscoped_array<C> is like gscoped_ptr<C>, except that the caller must allocate
571
// with new [] and the destructor deletes objects with delete [].
572
//
573
// As with gscoped_ptr<C>, a gscoped_array<C> either points to an object
574
// or is NULL.  A gscoped_array<C> owns the object that it points to.
575
// gscoped_array<T> is thread-compatible, and once you index into it,
576
// the returned objects have only the thread safety guarantees of T.
577
//
578
// Size: sizeof(gscoped_array<C>) == sizeof(C*)
579
template <class C>
580
class gscoped_array {
581
    MOVE_ONLY_TYPE_FOR_CPP_03(gscoped_array, RValue)
582
583
public:
584
    // The element type
585
    typedef C element_type;
586
587
    // Constructor.  Defaults to initializing with NULL.
588
    // There is no way to create an uninitialized gscoped_array.
589
    // The input parameter must be allocated with new [].
590
0
    explicit gscoped_array(C* p = NULL) : array_(p) {}
591
592
    // Constructor.  Move constructor for C++03 move emulation of this type.
593
    gscoped_array(RValue rvalue) : array_(rvalue.object->release()) {}
594
595
    // Destructor.  If there is a C object, delete it.
596
    // We don't need to test ptr_ == NULL because C++ does that for us.
597
0
    ~gscoped_array() {
598
0
        enum { type_must_be_complete = sizeof(C) };
599
0
        delete[] array_;
600
0
    }
601
602
    // operator=.  Move operator= for C++03 move emulation of this type.
603
    gscoped_array& operator=(RValue rhs) {
604
        reset(rhs.object->release());
605
        return *this;
606
    }
607
608
    // Reset.  Deletes the current owned object, if any.
609
    // Then takes ownership of a new object, if given.
610
    // this->reset(this->get()) works.
611
    void reset(C* p = NULL) {
612
        if (p != array_) {
613
            enum { type_must_be_complete = sizeof(C) };
614
            delete[] array_;
615
            array_ = p;
616
        }
617
    }
618
619
    // Get one element of the current object.
620
    // Will assert() if there is no current object, or index i is negative.
621
0
    C& operator[](ptrdiff_t i) const {
622
0
        assert(i >= 0);
623
0
        assert(array_ != NULL);
624
0
        return array_[i];
625
0
    }
626
627
    // Get a pointer to the zeroth element of the current object.
628
    // If there is no current object, return NULL.
629
0
    C* get() const { return array_; }
630
631
    // Allow gscoped_array<C> to be used in boolean expressions, but not
632
    // implicitly convertible to a real bool (which is dangerous).
633
    typedef C* gscoped_array::*Testable;
634
    operator Testable() const { return array_ ? &gscoped_array::array_ : NULL; }
635
636
    // Comparison operators.
637
    // These return whether two gscoped_array refer to the same object, not just to
638
    // two different but equal objects.
639
    bool operator==(C* p) const { return array_ == p; }
640
    bool operator!=(C* p) const { return array_ != p; }
641
642
    // Swap two scoped arrays.
643
    void swap(gscoped_array& p2) {
644
        C* tmp = array_;
645
        array_ = p2.array_;
646
        p2.array_ = tmp;
647
    }
648
649
    // Release an array.
650
    // The return value is the current pointer held by this object.
651
    // If this object holds a NULL pointer, the return value is NULL.
652
    // After this operation, this object will hold a NULL pointer,
653
    // and will not own the object any more.
654
    C* release() WARN_UNUSED_RESULT {
655
        C* retVal = array_;
656
        array_ = NULL;
657
        return retVal;
658
    }
659
660
private:
661
    C* array_;
662
663
    // Forbid comparison of different gscoped_array types.
664
    template <class C2>
665
    bool operator==(gscoped_array<C2> const& p2) const;
666
    template <class C2>
667
    bool operator!=(gscoped_array<C2> const& p2) const;
668
};
669
670
// Free functions
671
template <class C>
672
void swap(gscoped_array<C>& p1, gscoped_array<C>& p2) {
673
    p1.swap(p2);
674
}
675
676
template <class C>
677
bool operator==(C* p1, const gscoped_array<C>& p2) {
678
    return p1 == p2.get();
679
}
680
681
template <class C>
682
bool operator!=(C* p1, const gscoped_array<C>& p2) {
683
    return p1 != p2.get();
684
}
685
686
// DEPRECATED: Use gscoped_ptr<C, doris::FreeDeleter> instead.
687
//
688
// gscoped_ptr_malloc<> is similar to gscoped_ptr<>, but it accepts a
689
// second template argument, the functor used to free the object.
690
691
template <class C, class FreeProc = doris::FreeDeleter>
692
class gscoped_ptr_malloc {
693
    MOVE_ONLY_TYPE_FOR_CPP_03(gscoped_ptr_malloc, RValue)
694
695
public:
696
    // The element type
697
    typedef C element_type;
698
699
    // Constructor.  Defaults to initializing with NULL.
700
    // There is no way to create an uninitialized gscoped_ptr.
701
    // The input parameter must be allocated with an allocator that matches the
702
    // Free functor.  For the default Free functor, this is malloc, calloc, or
703
    // realloc.
704
    explicit gscoped_ptr_malloc(C* p = NULL) : ptr_(p) {}
705
706
    // Constructor.  Move constructor for C++03 move emulation of this type.
707
    gscoped_ptr_malloc(RValue rvalue) : ptr_(rvalue.object->release()) {}
708
709
    // Destructor.  If there is a C object, call the Free functor.
710
    ~gscoped_ptr_malloc() { reset(); }
711
712
    // operator=.  Move operator= for C++03 move emulation of this type.
713
    gscoped_ptr_malloc& operator=(RValue rhs) {
714
        reset(rhs.object->release());
715
        return *this;
716
    }
717
718
    // Reset.  Calls the Free functor on the current owned object, if any.
719
    // Then takes ownership of a new object, if given.
720
    // this->reset(this->get()) works.
721
    void reset(C* p = NULL) {
722
        if (ptr_ != p) {
723
            if (ptr_ != NULL) {
724
                FreeProc free_proc;
725
                free_proc(ptr_);
726
            }
727
            ptr_ = p;
728
        }
729
    }
730
731
    // Get the current object.
732
    // operator* and operator-> will cause an assert() failure if there is
733
    // no current object.
734
    C& operator*() const {
735
        assert(ptr_ != NULL);
736
        return *ptr_;
737
    }
738
739
    C* operator->() const {
740
        assert(ptr_ != NULL);
741
        return ptr_;
742
    }
743
744
    C* get() const { return ptr_; }
745
746
    // Allow gscoped_ptr_malloc<C> to be used in boolean expressions, but not
747
    // implicitly convertible to a real bool (which is dangerous).
748
    typedef C* gscoped_ptr_malloc::*Testable;
749
    operator Testable() const { return ptr_ ? &gscoped_ptr_malloc::ptr_ : NULL; }
750
751
    // Comparison operators.
752
    // These return whether a gscoped_ptr_malloc and a plain pointer refer
753
    // to the same object, not just to two different but equal objects.
754
    // For compatibility with the boost-derived implementation, these
755
    // take non-const arguments.
756
    bool operator==(C* p) const { return ptr_ == p; }
757
758
    bool operator!=(C* p) const { return ptr_ != p; }
759
760
    // Swap two scoped pointers.
761
    void swap(gscoped_ptr_malloc& b) {
762
        C* tmp = b.ptr_;
763
        b.ptr_ = ptr_;
764
        ptr_ = tmp;
765
    }
766
767
    // Release a pointer.
768
    // The return value is the current pointer held by this object.
769
    // If this object holds a NULL pointer, the return value is NULL.
770
    // After this operation, this object will hold a NULL pointer,
771
    // and will not own the object any more.
772
    C* release() WARN_UNUSED_RESULT {
773
        C* tmp = ptr_;
774
        ptr_ = NULL;
775
        return tmp;
776
    }
777
778
private:
779
    C* ptr_;
780
781
    // no reason to use these: each gscoped_ptr_malloc should have its own object
782
    template <class C2, class GP>
783
    bool operator==(gscoped_ptr_malloc<C2, GP> const& p) const;
784
    template <class C2, class GP>
785
    bool operator!=(gscoped_ptr_malloc<C2, GP> const& p) const;
786
};
787
788
template <class C, class FP>
789
void swap(gscoped_ptr_malloc<C, FP>& a, gscoped_ptr_malloc<C, FP>& b) {
790
    a.swap(b);
791
}
792
793
template <class C, class FP>
794
bool operator==(C* p, const gscoped_ptr_malloc<C, FP>& b) {
795
    return p == b.get();
796
}
797
798
template <class C, class FP>
799
bool operator!=(C* p, const gscoped_ptr_malloc<C, FP>& b) {
800
    return p != b.get();
801
}
802
803
// A function to convert T* into gscoped_ptr<T>
804
// Doing e.g. make_gscoped_ptr(new FooBarBaz<type>(arg)) is a shorter notation
805
// for gscoped_ptr<FooBarBaz<type>>(new FooBarBaz<type>(arg))
806
template <typename T>
807
gscoped_ptr<T> make_gscoped_ptr(T* ptr) {
808
    return gscoped_ptr<T>(ptr);
809
}