]>
git.saurik.com Git - apple/icu.git/blob - icuSources/common/sharedptr.h
2 *******************************************************************************
3 * Copyright (C) 2014, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 *******************************************************************************
8 *******************************************************************************
11 #ifndef __SHARED_PTR_H__
12 #define __SHARED_PTR_H__
14 #include "unicode/uobject.h"
20 // Wrap u_atomic_int32_t in a UMemory so that we allocate them in the same
21 // way we allocate all other ICU objects.
22 struct AtomicInt
: public UMemory
{
23 u_atomic_int32_t value
;
27 * SharedPtr are shared pointers that support copy-on-write sematics.
28 * SharedPtr makes the act of copying large objects cheap by deferring the
29 * cost of the copy to the first write operation after the copy.
31 * A SharedPtr<T> instance can refer to no object or an object of type T.
32 * T must have a clone() method that copies
33 * the object and returns a pointer to the copy. Copy and assignment of
34 * SharedPtr instances are cheap because they only involve copying or
35 * assigning the SharedPtr instance, not the T object which could be large.
36 * Although many SharedPtr<T> instances may refer to the same T object,
37 * clients can still assume that each SharedPtr<T> instance has its own
38 * private instance of T because each SharedPtr<T> instance offers only a
39 * const view of its T object through normal pointer operations. If a caller
40 * must change a T object through its SharedPtr<T>, it can do so by calling
41 * readWrite() on the SharedPtr instance. readWrite() ensures that the
42 * SharedPtr<T> really does have its own private T object by cloning it if
43 * it is shared by using its clone() method. SharedPtr<T> instances handle
44 * management by reference counting their T objects. T objects that are
45 * referenced by no SharedPtr<T> instances get deleted automatically.
48 // TODO (Travis Keep): Leave interface the same, but find a more efficient
49 // implementation that is easier to understand.
54 * Constructor. If there is a memory allocation error creating
55 * reference counter then this object will contain NULL, and adopted
56 * pointer will be freed. Note that when passing NULL or no argument to
57 * constructor, no memory allocation error can happen as NULL pointers
58 * are never reference counted.
60 explicit SharedPtr(T
*adopted
=NULL
) : ptr(adopted
), refPtr(NULL
) {
62 refPtr
= new AtomicInt();
75 SharedPtr(const SharedPtr
<T
> &other
) :
76 ptr(other
.ptr
), refPtr(other
.refPtr
) {
78 umtx_atomic_inc(&refPtr
->value
);
83 * assignment operator.
85 SharedPtr
<T
> &operator=(const SharedPtr
<T
> &other
) {
86 if (ptr
!= other
.ptr
) {
87 SharedPtr
<T
> newValue(other
);
98 if (umtx_atomic_dec(&refPtr
->value
) == 0) {
106 * reset adopts a new pointer. On success, returns TRUE.
107 * On memory allocation error creating reference counter for adopted
108 * pointer, returns FALSE while leaving this instance unchanged.
110 bool reset(T
*adopted
) {
111 SharedPtr
<T
> newValue(adopted
);
112 if (adopted
!= NULL
&& newValue
.ptr
== NULL
) {
113 // We couldn't allocate ref counter.
121 * reset makes this instance refer to no object.
128 * count returns how many SharedPtr instances, including this one,
129 * refer to the T object. Used for testing. Clients need not use in
132 int32_t count() const {
133 if (refPtr
== NULL
) {
136 return umtx_loadAcquire(refPtr
->value
);
140 * Swaps this instance with other.
142 void swap(SharedPtr
<T
> &other
) {
143 T
*tempPtr
= other
.ptr
;
144 AtomicInt
*tempRefPtr
= other
.refPtr
;
146 other
.refPtr
= refPtr
;
151 const T
*operator->() const {
155 const T
&operator*() const {
159 bool operator==(const T
*other
) const {
163 bool operator!=(const T
*other
) const {
168 * readOnly gives const access to this instance's T object. If this
169 * instance refers to no object, returns NULL.
171 const T
*readOnly() const {
176 * readWrite returns a writable pointer to its T object copying it first
177 * using its clone() method if it is shared.
178 * On memory allocation error or if this instance refers to no object,
179 * this method returns NULL leaving this instance unchanged.
181 * If readWrite() returns a non NULL pointer, it guarantees that this
182 * object holds the only reference to its T object enabling the caller to
183 * perform mutations using the returned pointer without affecting other
184 * SharedPtr objects. However, the non-constness of readWrite continues as
185 * long as the returned pointer is in scope. Therefore it is an API
186 * violation to call readWrite() on A; perform B = A; and then proceed to
187 * mutate A via its writeable pointer as that would be the same as setting
188 * B = A while A is changing. The returned pointer is guaranteed to be
189 * valid only while this object is in scope because this object maintains
190 * ownership of its T object. Therefore, callers must never attempt to
191 * delete the returned writeable pointer. The best practice with readWrite
192 * is this: callers should use the returned pointer from readWrite() only
193 * within the same scope as that call to readWrite, and that scope should
194 * be made as small as possible avoiding overlap with other operatios on
198 int32_t refCount
= count();
202 T
*result
= (T
*) ptr
->clone();
203 if (result
== NULL
) {
204 // Memory allocation error
207 if (!reset(result
)) {
215 // No heap allocation. Use only stack.
216 static void * U_EXPORT2
operator new(size_t size
);
217 static void * U_EXPORT2
operator new[](size_t size
);
218 #if U_HAVE_PLACEMENT_NEW
219 static void * U_EXPORT2
operator new(size_t, void *ptr
);