1 /* GENERATED SOURCE. DO NOT MODIFY. */ 2 // © 2016 and later: Unicode, Inc. and others. 3 // License & terms of use: http://www.unicode.org/copyright.html#License 4 /* 5 ******************************************************************************* 6 * Copyright (C) 2013-2014, International Business Machines 7 * Corporation and others. All Rights Reserved. 8 ******************************************************************************* 9 * SharedObject.java, ported from sharedobject.h/.cpp 10 * 11 * C++ version created on: 2013dec19 12 * created by: Markus W. Scherer 13 */ 14 15 package ohos.global.icu.impl.coll; 16 17 import java.util.concurrent.atomic.AtomicInteger; 18 19 import ohos.global.icu.util.ICUCloneNotSupportedException; 20 21 /** 22 * Base class for shared, reference-counted, auto-deleted objects. 23 * Java subclasses are mutable and must implement clone(). 24 * 25 * <p>In C++, the SharedObject base class is used for both memory and ownership management. 26 * In Java, memory management (deletion after last reference is gone) 27 * is up to the garbage collector, 28 * but the reference counter is still used to see whether the referent is the sole owner. 29 * 30 * <p>Usage: 31 * <pre> 32 * class S extends SharedObject { 33 * public clone() { ... } 34 * } 35 * 36 * // Either use the nest class Reference (which costs an extra allocation), 37 * // or duplicate its code in the class that uses S 38 * // (which duplicates code and is more error-prone). 39 * class U { 40 * // For read-only access, use s.readOnly(). 41 * // For writable access, use S ownedS = s.copyOnWrite(); 42 * private SharedObject.Reference<S> s; 43 * // Returns a writable version of s. 44 * // If there is exactly one owner, then s itself is returned. 45 * // If there are multiple owners, then s is replaced with a clone, 46 * // and that is returned. 47 * private S getOwnedS() { 48 * return s.copyOnWrite(); 49 * } 50 * public U clone() { 51 * ... 52 * c.s = s.clone(); 53 * ... 54 * } 55 * } 56 * 57 * class V { 58 * // For read-only access, use s directly. 59 * // For writable access, use S ownedS = getOwnedS(); 60 * private S s; 61 * // Returns a writable version of s. 62 * // If there is exactly one owner, then s itself is returned. 63 * // If there are multiple owners, then s is replaced with a clone, 64 * // and that is returned. 65 * private S getOwnedS() { 66 * if(s.getRefCount() > 1) { 67 * S ownedS = s.clone(); 68 * s.removeRef(); 69 * s = ownedS; 70 * ownedS.addRef(); 71 * } 72 * return s; 73 * } 74 * public U clone() { 75 * ... 76 * s.addRef(); 77 * ... 78 * } 79 * protected void finalize() { 80 * ... 81 * if(s != null) { 82 * s.removeRef(); 83 * s = null; 84 * } 85 * ... 86 * } 87 * } 88 * </pre> 89 * 90 * Either use only Java memory management, or use addRef()/removeRef(). 91 * Sharing requires reference-counting. 92 * 93 * TODO: Consider making this more widely available inside ICU, 94 * or else adopting a different model. 95 * @hide exposed on OHOS 96 */ 97 public class SharedObject implements Cloneable { 98 /** 99 * Similar to a smart pointer, basically a port of the static methods of C++ SharedObject. 100 * @hide exposed on OHOS 101 */ 102 public static final class Reference<T extends SharedObject> implements Cloneable { 103 private T ref; 104 Reference(T r)105 public Reference(T r) { 106 ref = r; 107 if(r != null) { 108 r.addRef(); 109 } 110 } 111 112 @SuppressWarnings("unchecked") 113 @Override clone()114 public Reference<T> clone() { 115 Reference<T> c; 116 try { 117 c = (Reference<T>)super.clone(); 118 } catch (CloneNotSupportedException e) { 119 // Should never happen. 120 throw new ICUCloneNotSupportedException(e); 121 } 122 if(ref != null) { 123 ref.addRef(); 124 } 125 return c; 126 } 127 readOnly()128 public T readOnly() { return ref; } 129 130 /** 131 * Returns a writable version of the reference. 132 * If there is exactly one owner, then the reference itself is returned. 133 * If there are multiple owners, then the reference is replaced with a clone, 134 * and that is returned. 135 */ copyOnWrite()136 public T copyOnWrite() { 137 T r = ref; 138 if(r.getRefCount() <= 1) { return r; } 139 @SuppressWarnings("unchecked") 140 T r2 = (T)r.clone(); 141 r.removeRef(); 142 ref = r2; 143 r2.addRef(); 144 return r2; 145 } 146 clear()147 public void clear() { 148 if(ref != null) { 149 ref.removeRef(); 150 ref = null; 151 } 152 } 153 154 @Override finalize()155 protected void finalize() throws Throwable { 156 super.finalize(); 157 clear(); 158 } 159 } 160 161 /** Initializes refCount to 0. */ SharedObject()162 public SharedObject() {} 163 164 /** Initializes refCount to 0. */ 165 @Override clone()166 public SharedObject clone() { 167 SharedObject c; 168 try { 169 c = (SharedObject)super.clone(); 170 } catch (CloneNotSupportedException e) { 171 // Should never happen. 172 throw new ICUCloneNotSupportedException(e); 173 } 174 c.refCount = new AtomicInteger(); 175 return c; 176 } 177 178 /** 179 * Increments the number of references to this object. Thread-safe. 180 */ addRef()181 public final void addRef() { refCount.incrementAndGet(); } 182 /** 183 * Decrements the number of references to this object, 184 * and auto-deletes "this" if the number becomes 0. Thread-safe. 185 */ removeRef()186 public final void removeRef() { 187 // Deletion in Java is up to the garbage collector. 188 refCount.decrementAndGet(); 189 } 190 191 /** 192 * Returns the reference counter. Uses a memory barrier. 193 */ getRefCount()194 public final int getRefCount() { return refCount.get(); } 195 deleteIfZeroRefCount()196 public final void deleteIfZeroRefCount() { 197 // Deletion in Java is up to the garbage collector. 198 } 199 200 private AtomicInteger refCount = new AtomicInteger(); 201 } 202