summaryrefslogtreecommitdiff
path: root/o3tl/inc/o3tl/heap_ptr.hxx
blob: 3fe1e1c6e541c5c6981982f8ee5e78c32391e75f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef INCLUDED_O3TL_HEAP_PTR_HXX
#define INCLUDED_O3TL_HEAP_PTR_HXX


#include <boost/assert.hpp>
#include <boost/checked_delete.hpp>


namespace o3tl
{
/** heap_ptr<> owns an object on the heap, which will be automatically
    deleted, when ~heap_ptr<>() is called.

    Applicability
    -------------
    heap_ptr<> can be used for class members on the heap.
      - One cannot forget to delete them in the destructor.
      - Constness will be transfered from the owning instance.

    heap_ptr<> can also be used as smart pointer in function bodies to
    ensure exception safety.

    Special Characteristics
    -----------------------
      - heap_ptr<> transfers constness from the owning object to
        the pointed to object. Such it behaves like if *get() would be
        a normal member of the owning object, not a pointer member.
        This is preferable to the normal pointer behaviour, because
        if an object is owned by another one, it is normally part of
        its state.

      - heap_ptr<> provides a ->release() function

      - For reasons of simplicity and portability ->is()
        is preferred over the safe-bool idiom.

    Copyability
    -----------
    heap_ptr is non copyable.
      - It forbids the copyconstructor and operator=(self).

      - Owning classes will automatically be non copyable, if they do not
        redefine those two functions themselves.

    Incomplete Types
    ----------------
    heap_ptr<> also works with incomplete types. You only need to write
        class T;
    but need not include <T>.hxx.

    If you use heap_ptr<> with an incomplete type, the owning class
    needs to define a non-inline destructor. Else the compiler will
    complain.
*/
template <class T>
class heap_ptr
{
  public:
    typedef T               element_type;       /// Provided for generic programming.
    typedef heap_ptr<T>     self;

#ifndef __SUNPRO_CC
    typedef T * (self::*    safe_bool )();
#endif

    /// Now, pass_heapObject is owned by this.
    explicit            heap_ptr(
                            T *                 pass_heapObject = 0 );
                        ~heap_ptr();


    /** Identical to reset(), except of the return value.
        @see heap_ptr<>::reset()
    */
    self &              operator=(
                            T *                 pass_heapObject );
    const T &           operator*() const;
    T &                 operator*();
    const T *           operator->() const;
    T *                 operator->();

    /// True, if pHeapObject != 0.
#ifndef __SUNPRO_CC
                        operator safe_bool() const;
#else // workaround opt bug of Sun C++ compiler, when compiling with -xO3
                        operator bool() const;
#endif


    /** This deletes any prevoiusly existing ->pHeapObject.
        Now, pass_heapObject, if != 0, is owned by this.

        @onerror
        Ignores self-assignment.
        Such, multiple assignment of the same pointer to the same
        instance of heap_ptr<> is possible (though not recommended).
    */
    void                reset(
                            T *                 pass_heapObject );
    /** @return     An object on the heap that must be deleted by the caller,
                    or 0.

        @postcond   get() == 0;
    */
    T *                 release();
    void                swap(
                            self &              io_other );

    /// True, if pHeapObject != 0.
    bool                is() const;
    const T *           get() const;
    T *                 get();

  private:
    // Forbidden functions:
                          heap_ptr( const self & );   /// Prevent copies.
    self &              operator=( const self & );  /// Prevent copies.

    /// @attention Does not set ->pHeapObject = 0.
      void              internal_delete();

  // DATA
    /// Will be deleted, when *this is destroyed.
    T *                 pHeapObject;
};


/** Supports the semantic of std::swap(). Provided as an aid to
    generic programming.
*/
template<class T>
inline void
swap( heap_ptr<T> &       io_a,
      heap_ptr<T> &       io_b )
{
    io_a.swap(io_b);
}



// IMPLEMENTATION

template <class T>
inline void
heap_ptr<T>::internal_delete()
{
    ::boost::checked_delete(pHeapObject);

    // Do not set pHeapObject to 0, because
    //   that is reset to a value in all code
    //   where internal_delete() is used.
}

template <class T>
inline
heap_ptr<T>::heap_ptr( T * pass_heapObject )
    : pHeapObject(pass_heapObject)
{
}

template <class T>
inline
heap_ptr<T>::~heap_ptr()
{
    internal_delete();
}

template <class T>
inline heap_ptr<T> &
heap_ptr<T>::operator=(T * pass_heapObject)
{
    reset(pass_heapObject);
    return *this;
}

template <class T>
inline const T &
heap_ptr<T>::operator*() const
{
    BOOST_ASSERT( pHeapObject != 0
                  && "Accessing a heap_ptr<>(0)." );
    return *pHeapObject;
}

template <class T>
inline T &
heap_ptr<T>::operator*()
{
    BOOST_ASSERT( pHeapObject != 0
                  && "Accessing a heap_ptr<>(0)." );
    return *pHeapObject;
}

template <class T>
inline const T *
heap_ptr<T>::operator->() const
{
    return pHeapObject;
}

template <class T>
inline T *
heap_ptr<T>::operator->()
{
    return pHeapObject;
}

#ifndef __SUNPRO_CC

template <class T>
inline
heap_ptr<T>::operator typename heap_ptr<T>::safe_bool() const
{
    return is()
            ? safe_bool(&self::get)
            : safe_bool(0);
}

#else

template <class T>
inline heap_ptr<T>::operator bool() const
{
    return is();
}

#endif // !defined(__SUNPRO_CC)



template <class T>
void
heap_ptr<T>::reset(T * pass_heapObject)
{
    if (    pHeapObject != 0
        &&  pHeapObject == pass_heapObject)
        return;

    internal_delete();
    pHeapObject = pass_heapObject;
}

template <class T>
T *
heap_ptr<T>::release()
{
    T * ret = pHeapObject;
    pHeapObject = 0;
    return ret;
}

template <class T>
void
heap_ptr<T>::swap(self & io_other)
{
    T * temp = io_other.pHeapObject;
    io_other.pHeapObject = pHeapObject;
    pHeapObject = temp;
}

template <class T>
inline bool
heap_ptr<T>::is() const
{
    return pHeapObject != 0;
}

template <class T>
inline const T *
heap_ptr<T>::get() const
{
    return pHeapObject;
}

template <class T>
inline T *
heap_ptr<T>::get()
{
    return pHeapObject;
}


}   // namespace o3tl
#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */