~alinuxninja/nginx-edge/trunk

« back to all changes in this revision

Viewing changes to debian/modules/ngx_pagespeed/psol/include/pagespeed/kernel/base/ref_counted_ptr.h

  • Committer: Vivian
  • Date: 2015-12-04 18:20:11 UTC
  • Revision ID: git-v1:a36f2bc32e884f7473b3a47040e5411306144d7d
* Do not extract psol.tar.gz

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright 2010 Google Inc.
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
 
// Author: jmarantz@google.com (Joshua Marantz)
18
 
//
19
 
// Implements a generic ref-counted class, with full sharing.  This
20
 
// class does *not* implement copy-on-write semantics, but it provides
21
 
// 'unique()', which helps implement COW at a higher level.
22
 
//
23
 
// There are two pointer templates here:
24
 
// - RefCountedPtr<T> --- requires T to inherit off RefCounted<T>,
25
 
//   stores it by pointer to supports full polymorphism.
26
 
// - RefCountedObj<T> --- no requirements on T besides default and copy
27
 
//   construction, but stores T by value so it must always store exactly T.
28
 
//
29
 
// TODO(jmaessen): explore adding C++x0 shared_ptr support
30
 
 
31
 
#ifndef PAGESPEED_KERNEL_UTIL_REF_COUNTED_PTR_H_
32
 
#define PAGESPEED_KERNEL_UTIL_REF_COUNTED_PTR_H_
33
 
 
34
 
#include "base/logging.h"
35
 
#include "pagespeed/kernel/base/atomic_int32.h"
36
 
#include "pagespeed/kernel/base/basictypes.h"
37
 
 
38
 
namespace net_instaweb {
39
 
 
40
 
template<class T>
41
 
class RefCounted {
42
 
 public:
43
 
  RefCounted() : ref_count_(0) {}
44
 
  ~RefCounted() { DCHECK_EQ(0, ref_count_.value()); }
45
 
 
46
 
  void Release() {
47
 
    if (ref_count_.BarrierIncrement(-1) == 0) {
48
 
      delete static_cast<T*>(this);
49
 
    }
50
 
  }
51
 
 
52
 
  void AddRef() {
53
 
    ref_count_.NoBarrierIncrement(1);
54
 
  }
55
 
 
56
 
  bool HasOneRef() {
57
 
    return (ref_count_.value() == 1);
58
 
  }
59
 
 
60
 
 private:
61
 
  AtomicInt32 ref_count_;
62
 
  DISALLOW_COPY_AND_ASSIGN(RefCounted<T>);
63
 
};
64
 
 
65
 
// Template class to help make reference-counted pointers.  You can use
66
 
// a typedef or subclass RefCountedPtr<YourClass>.  YourClass has to inherit
67
 
// off RefCounted<T>.
68
 
template<class T>
69
 
class RefCountedPtr {
70
 
 public:
71
 
  RefCountedPtr() : ptr_(NULL) {}
72
 
  explicit RefCountedPtr(T* t) : ptr_(t) {
73
 
    if (t != NULL) {
74
 
      t->AddRef();
75
 
    }
76
 
  }
77
 
 
78
 
  RefCountedPtr(const RefCountedPtr<T>& src)
79
 
      : ptr_(src.ptr_) {
80
 
    if (ptr_ != NULL) {
81
 
      ptr_->AddRef();
82
 
    }
83
 
  }
84
 
 
85
 
  template<class U>
86
 
  explicit RefCountedPtr(const RefCountedPtr<U>& src)
87
 
      : ptr_(static_cast<T*>(src.ptr_)) {
88
 
    if (ptr_ != NULL) {
89
 
      ptr_->AddRef();
90
 
    }
91
 
  }
92
 
 
93
 
  ~RefCountedPtr() {
94
 
    if (ptr_ != NULL) {
95
 
      ptr_->Release();
96
 
    }
97
 
  }
98
 
 
99
 
  RefCountedPtr<T>& operator=(const RefCountedPtr<T>& other) {
100
 
    // ref before deref to deal with self-assignment.
101
 
    if (other.ptr_ != NULL) {
102
 
      other.ptr_->AddRef();
103
 
    }
104
 
    if (ptr_ != NULL) {
105
 
      ptr_->Release();
106
 
    }
107
 
    ptr_ = other.ptr_;
108
 
    return *this;
109
 
  }
110
 
 
111
 
  template<class U>
112
 
  RefCountedPtr<T>& operator=(const RefCountedPtr<U>& other) {
113
 
    if (other.ptr_ != NULL) {
114
 
      other.ptr_->AddRef();
115
 
    }
116
 
    if (ptr_ != NULL) {
117
 
      ptr_->Release();
118
 
    }
119
 
    ptr_ = static_cast<T*>(other.ptr_);
120
 
    return *this;
121
 
  }
122
 
 
123
 
  T* operator->() const { return ptr_; }
124
 
  T* get() const { return ptr_; }
125
 
 
126
 
  // Determines whether any other RefCountedPtr objects share the same
127
 
  // storage.  This can be used to create copy-on-write semantics if
128
 
  // desired.
129
 
  bool unique() const { return !this->ptr_ || this->ptr_->HasOneRef(); }
130
 
 
131
 
  template<typename U>
132
 
  RefCountedPtr<U> StaticCast() const {
133
 
    return RefCountedPtr<U>(static_cast<U*>(this->get()));
134
 
  }
135
 
 
136
 
  void clear() {
137
 
    *this = RefCountedPtr();
138
 
  }
139
 
  void reset(T* ptr) {
140
 
    *this = RefCountedPtr(ptr);
141
 
  }
142
 
  void reset(const RefCountedPtr& src) {
143
 
    *this = src;
144
 
  }
145
 
 
146
 
 private:
147
 
  template <class U> friend class RefCountedPtr;
148
 
  operator void*() const;  // don't compare directly to NULL; use get()
149
 
  operator T*() const;     // don't assign directly to pointer; use get()
150
 
 
151
 
  // Note that copy and assign of RefCountedPtr is allowed -- that
152
 
  // is how the reference counts are updated.
153
 
  T* ptr_;
154
 
};
155
 
 
156
 
// If you can't inherit off RefCounted due to using a pre-existing
157
 
// class, you can use RefCountedObj instead. This however is limited to
158
 
// having a single type (so no polymorphism). It also has slightly
159
 
// different semantics in that it initializes to a default-constructed object
160
 
// and not NULL.
161
 
template<class T>
162
 
class RefCountedObj {
163
 
 public:
164
 
  RefCountedObj() : data_ptr_(new Data()) {}
165
 
  explicit RefCountedObj(const T& val) : data_ptr_(new Data(val)) {}
166
 
 
167
 
  // Determines whether any other RefCountedObj objects share the same
168
 
  // storage.  This can be used to create copy-on-write semantics if
169
 
  // desired.
170
 
  bool unique() const { return data_ptr_.unique(); }
171
 
 
172
 
  T* get() { return &data_ptr_->value; }
173
 
  const T* get() const { return &data_ptr_->value; }
174
 
  T* operator->() { return &data_ptr_->value; }
175
 
  const T* operator->() const { return &data_ptr_->value; }
176
 
  T& operator*() { return data_ptr_->value; }
177
 
  const T& operator*() const { return data_ptr_->value; }
178
 
 
179
 
  // Sets the object to contain a new value, detaching it
180
 
  // from any other RefCountedObj instances that were previously
181
 
  // sharing data.
182
 
  void reset(const T& val) { data_ptr_.reset(new Data(val)); }
183
 
 
184
 
 protected:
185
 
  struct Data : public RefCounted<Data> {
186
 
    Data() {}
187
 
    explicit Data(const T& val) : value(val) {}
188
 
    T value;
189
 
  };
190
 
 
191
 
  RefCountedPtr<Data> data_ptr_;
192
 
 
193
 
 private:
194
 
  operator void*() const;  // don't compare directly to NULL; use get()
195
 
  operator T*() const;     // don't assign directly to pointer; use get()
196
 
 
197
 
  // Copying, etc., are OK thanks to data_ptr_.
198
 
};
199
 
 
200
 
// Macro for users implementing C++ ref-counted classes to prevent
201
 
// explicit destruction.  Once a class is reference counted, it
202
 
// should never be stack-allocated or explicitly deleted.  It should
203
 
// only be deleted by the reference count object.  Put this declaration
204
 
// in the 'protected:' or 'private:' section, and group it with
205
 
// a destructor declaration.
206
 
//
207
 
// This is only required for RefCountedPtr<T>, not RefCountedObj<T>.
208
 
//
209
 
#define REFCOUNT_FRIEND_DECLARATION(class_name) \
210
 
  friend class net_instaweb::RefCounted<class_name>
211
 
 
212
 
}  // namespace net_instaweb
213
 
 
214
 
#endif  // PAGESPEED_KERNEL_UTIL_REF_COUNTED_PTR_H_