summaryrefslogtreecommitdiff
path: root/ACE/ace/Bound_Ptr.h
blob: 3b736a149420b800c78df23f498514f43ef3cfb1 (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
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
// -*- C++ -*-

//=============================================================================
/**
 *  @file    Bound_Ptr.h
 *
 *  @author Christopher Kohlhoff <chris@kohlhoff.com>
 *  @author Boris Kolpackov <boris@codesynthesis.com>
 */
//=============================================================================

#ifndef ACE_BOUND_PTR_H
#define ACE_BOUND_PTR_H

#include /**/ "ace/pre.h"

#include /**/ "ace/config-all.h"

#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */

ACE_BEGIN_VERSIONED_NAMESPACE_DECL

/**
 * @class ACE_Bound_Ptr_Counter
 *
 * @brief An ACE_Bound_Ptr_Counter<ACE_LOCK> object encapsulates an
 *        object reference count.
 *
 * Do not use this class directly, use ACE_Strong_Bound_Ptr or
 * ACE_Weak_Bound_Ptr instead.
 */
template <class ACE_LOCK>
class ACE_Bound_Ptr_Counter
{
public:
  /// Declare the dynamic allocation hooks.
  ACE_ALLOC_HOOK_DECLARE;

  ACE_Bound_Ptr_Counter (long init_obj_ref_count = 0);
  ~ACE_Bound_Ptr_Counter () = default;

  /// Create a ACE_Bound_Ptr_Counter<ACE_LOCK> and initialize the
  /// reference count to indicate ownership by a strong pointer.
  static ACE_Bound_Ptr_Counter<ACE_LOCK> *create_strong ();

  /// Increase both the object and counter reference counts and return
  /// the new object reference count. A return value of -1 indicates
  /// that the object has already been destroyed.
  static long attach_strong (ACE_Bound_Ptr_Counter<ACE_LOCK> *counter);

  /// Decreases both the object and counter reference counts and
  /// deletes whichever has no more references. Returns the new object
  /// reference count.
  static long detach_strong (ACE_Bound_Ptr_Counter<ACE_LOCK> *counter);

  /// Create a ACE_Bound_Ptr_Counter<ACE_LOCK> and initialize the
  /// reference count to indicate no ownership.
  static ACE_Bound_Ptr_Counter<ACE_LOCK> *create_weak ();

  /// Increase the counter reference count and return argument.
  static void attach_weak (ACE_Bound_Ptr_Counter<ACE_LOCK> *counter);

  /// Decreases the counter reference count and deletes the counter if
  /// it has no more references.
  static void detach_weak (ACE_Bound_Ptr_Counter<ACE_LOCK> *counter);

  /// Determine whether the object has been deleted.
  static bool object_was_deleted (ACE_Bound_Ptr_Counter<ACE_LOCK> *counter);

private:
  /// Allocate a new ACE_Bound_Ptr_Counter<ACE_LOCK> instance,
  /// returning NULL if it cannot be created.
  static ACE_Bound_Ptr_Counter<ACE_LOCK> *internal_create (long init_obj_ref_count);

private:
  /// Reference count of underlying object. Is set to -1 once the
  /// object has been destroyed to indicate to all weak pointers that
  /// it is no longer valid.
  long obj_ref_count_;

  /// Reference count of this counter.
  long self_ref_count_;

  /// Mutex variable to synchronize access to the reference counts.
  ACE_LOCK lock_;
};

// Forward decl.
template <class X, class ACE_LOCK> class ACE_Weak_Bound_Ptr;

/**
 * @class ACE_Strong_Bound_Ptr
 *
 * @brief This class implements support for a reference counted
 *        pointer.
 *
 * Assigning or copying instances of an ACE_Strong_Bound_Ptr will
 * automatically increment the reference count of the underlying object.
 * When the last instance of an ACE_Strong_Bound_Ptr that references a
 * particular object is destroyed or overwritten, it will invoke delete
 * on its underlying pointer.
 */
template <class X, class ACE_LOCK>
class ACE_Strong_Bound_Ptr
{
public:
  /// Constructor that initializes an ACE_Strong_Bound_Ptr to point to the
  /// object \<p\> immediately.
  explicit ACE_Strong_Bound_Ptr (X *p = 0);

  /// Copy constructor binds @c this and @a r to the same object.
  ACE_Strong_Bound_Ptr (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r);

  /// Constructor binds @c this and @a r to the same object.
  ACE_Strong_Bound_Ptr (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r);

  /// Copy constructor binds @c this and @a r to the same object if
  /// Y* can be implicitly converted to X*.
  template <class Y>
  ACE_Strong_Bound_Ptr (const ACE_Strong_Bound_Ptr<Y, ACE_LOCK> &r)
      : counter_ (r.counter_),
        ptr_ (dynamic_cast<X*>(r.ptr_))
  {
    // This ctor is temporarily defined here to increase our chances
    // of being accepted by broken compilers.
    //
    COUNTER::attach_strong (this->counter_);
  }

  /// Destructor.
  ~ACE_Strong_Bound_Ptr ();

  /// Assignment operator that binds @c this and @a r to the same object.
  void operator = (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r);

  /// Assignment operator that binds @c this and @a r to the same object.
  void operator = (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r);

  /// Assignment operator that binds @c this and @a r to the same object
  /// if Y* can be implicitly converted to X*.
  template <class Y>
  ACE_Weak_Bound_Ptr<X, ACE_LOCK>&
  operator= (const ACE_Strong_Bound_Ptr<Y, ACE_LOCK> &r)
  {
    // This operator is temporarily defined here to increase our chances
    // of being accepted by broken compilers.
    //

    // This will work if &r == this, by first increasing the ref count

    COUNTER *new_counter = r.counter_;
    X* new_ptr = dynamic_cast<X*> (r.ptr_);
    COUNTER::attach_strong (new_counter);
    if (COUNTER::detach_strong (this->counter_) == 0)
      delete this->ptr_;
    this->counter_ = new_counter;
    this->ptr_ = new_ptr;

    return *this;
  }

  /// Equality operator that returns @c true if both
  /// ACE_Strong_Bound_Ptr instances point to the same underlying
  /// object.
  /**
   * @note It also returns @c true if both objects have just been
   *       instantiated and not used yet.
   */
  bool operator == (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r) const;

  /// Equality operator that returns true if the ACE_Strong_Bound_Ptr
  /// and ACE_Weak_Bound_Ptr objects point to the same underlying
  /// object.
  /**
   * @note It also returns @c true if both objects have just been
   *       instantiated and not used yet.
   */
  bool operator == (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r) const;

  /// Equality operator that returns @c true if the
  /// ACE_Strong_Bound_Ptr and the raw pointer point to the same
  /// underlying object.
  bool operator == (X *p) const;

  /// Inequality operator, which is the opposite of equality.
  bool operator != (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r) const;

  /// Inequality operator, which is the opposite of equality.
  bool operator != (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r) const;

  /// Inequality operator, which is the opposite of equality.
  bool operator != (X *p) const;

  /// Redirection operator
  X *operator-> () const;

  /// Dereference operator
  X &operator * () const;

  /// Get the pointer value.
  X *get () const;

  /// Resets the ACE_Strong_Bound_Ptr to refer to a different
  /// underlying object.
  void reset (X *p = 0);

  /// Allows us to check for NULL on all ACE_Strong_Bound_Ptr
  /// objects.
  bool null () const;

  /// Declare the dynamic allocation hooks.
  ACE_ALLOC_HOOK_DECLARE;

private:
  friend class ACE_Weak_Bound_Ptr<X, ACE_LOCK>;

  template <class Y, class L>
  friend class ACE_Strong_Bound_Ptr;

  /// The ACE_Bound_Ptr_Counter type.
  typedef ACE_Bound_Ptr_Counter<ACE_LOCK> COUNTER;

  /// The reference counter.
  COUNTER *counter_;

  /// The underlying object.
  X *ptr_;
};

/**
 * @class ACE_Weak_Bound_Ptr
 *
 * @brief This class implements support for a weak pointer that complements
 * ACE_Strong_Bound_Ptr.
 *
 * Unlike ACE_Strong_Bound_Ptr, assigning or copying instances of an
 * ACE_Weak_Bound_Ptr will not automatically increment the reference
 * count of the underlying object. What ACE_Weak_Bound_Ptr does is
 * preserve the knowledge that the object is in fact reference
 * counted, and thus provides an alternative to raw pointers where
 * non-ownership associations must be maintained. When the last
 * instance of an ACE_Strong_Bound_Ptr that references a particular
 * object is destroyed or overwritten, the corresponding
 * ACE_Weak_Bound_Ptr instances are set to NULL.
 */
template <class X, class ACE_LOCK>
class ACE_Weak_Bound_Ptr
{
public:
  /// Constructor that initializes an ACE_Weak_Bound_Ptr to point to
  /// the object \<p\> immediately.
  explicit ACE_Weak_Bound_Ptr (X *p = 0);

  /// Copy constructor binds @c this and @a r to the same object.
  ACE_Weak_Bound_Ptr (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r);

  /// Constructor binds @c this and @a r to the same object.
  ACE_Weak_Bound_Ptr (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r);

  /// Destructor.
  ~ACE_Weak_Bound_Ptr ();

  /// Assignment operator that binds @c this and @a r to the same object.
  void operator = (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r);

  /// Assignment operator that binds @c this and @a r to the same object.
  void operator = (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r);

  /// Equality operator that returns @c true if both
  /// ACE_Weak_Bound_Ptr objects point to the same underlying object.
  /**
   * @note It also returns @c true if both objects have just been
   *       instantiated and not used yet.
   */
  bool operator == (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r) const;

  /// Equality operator that returns @c true if the ACE_Weak_Bound_Ptr
  /// and ACE_Strong_Bound_Ptr objects point to the same underlying
  /// object.
  /**
   * @note It also returns @c true if both objects have just been
   *       instantiated and not used yet.
   */
  bool operator == (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r) const;

  /// Equality operator that returns @c true if the ACE_Weak_Bound_Ptr
  /// and the raw pointer point to the same underlying object.
  bool operator == (X *p) const;

  /// Inequality operator, which is the opposite of equality.
  bool operator != (const ACE_Weak_Bound_Ptr<X, ACE_LOCK> &r) const;

  /// Inequality operator, which is the opposite of equality.
  bool operator != (const ACE_Strong_Bound_Ptr<X, ACE_LOCK> &r) const;

  /// Inequality operator, which is the opposite of equality.
  bool operator != (X *p) const;

  /// Redirection operator.
  /**
   * It returns a temporary strong pointer and makes use of the
   * chaining properties of operator-> to ensure that the underlying
   * object does not disappear while you are using it.  If you are
   * certain of the lifetimes of the object, and do not want to incur
   * the locking overhead, then use the unsafe_get method instead.
   */
  ACE_Strong_Bound_Ptr<X, ACE_LOCK> operator-> () const;

  /// Obtain a strong pointer corresponding to this weak pointer. This
  /// function is useful to create a temporary strong pointer for
  /// conversion to a reference.
  ACE_Strong_Bound_Ptr<X, ACE_LOCK> strong () const;

  /// Get the pointer value. Warning: this does not affect the
  /// reference count of the underlying object, so it may disappear on
  /// you while you are using it if you are not careful.
  X *unsafe_get () const;

  /// Resets the ACE_Weak_Bound_Ptr to refer to a different underlying
  /// object.
  void reset (X *p = 0);

  /// Increment the reference count on the underlying object.
  /**
   * Returns the new reference count on the object. This function may
   * be used to integrate the bound pointers into an external
   * reference counting mechanism such as those used by COM or CORBA
   * servants.
   */
  long add_ref ();

  /// Decrement the reference count on the underlying object, which is deleted
  /// if the count has reached zero.
  /**
   * Returns the new reference count on the object.  This function may
   * be used to integrate the bound pointers into an external
   * reference counting mechanism such as those used by COM or CORBA
   * servants.
   */
  long remove_ref ();

  /// Allows us to check for NULL on all ACE_Weak_Bound_Ptr objects.
  bool null () const;

  /// Declare the dynamic allocation hooks.
  ACE_ALLOC_HOOK_DECLARE;

private:
  friend class ACE_Strong_Bound_Ptr<X, ACE_LOCK>;

  /// The ACE_Bound_Ptr_Counter type.
  typedef ACE_Bound_Ptr_Counter<ACE_LOCK> COUNTER;

  /// The reference counter.
  COUNTER *counter_;

  /// The underlying object.
  X *ptr_;
};

ACE_END_VERSIONED_NAMESPACE_DECL

#if defined (__ACE_INLINE__)
#include "ace/Bound_Ptr.inl"
#endif /* __ACE_INLINE__ */

#include "ace/Bound_Ptr.cpp"

#include /**/ "ace/post.h"

#endif /* ACE_BOUND_PTR_H */