Coverage Report

Created: 2024-11-22 12:06

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